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 pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
658 if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
659 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) {
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);
1504 sprintf(s,"%s", pcop->name);
1506 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1509 rs = Safe_calloc(1,strlen(s)+1);
1514 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1518 // pCodeOp *pcop = aop->aop
1523 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1524 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1525 "aopget got unsupported aop->type");
1531 /* lock has the following meaning: When allocating temporary registers
1532 * for stack variables storage, the value of the temporary register is
1533 * saved on stack. Its value is restored at the end. This procedure is
1534 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1535 * a possibility that before a call to pic16_aopOp, a temporary register
1536 * is allocated for a while and it is freed after some time, this will
1537 * mess the stack and values will not be restored properly. So use lock=1
1538 * to allocate temporary registers used internally by the programmer, and
1539 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1540 * to inform the compiler developer about a possible bug. This is an internal
1541 * feature for developing the compiler -- VR */
1543 int _TempReg_lock = 0;
1544 /*-----------------------------------------------------------------*/
1545 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1546 /*-----------------------------------------------------------------*/
1547 pCodeOp *pic16_popGetTempReg(int lock)
1552 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1554 // werror(W_POSSBUG2, __FILE__, __LINE__);
1557 _TempReg_lock += lock;
1562 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1563 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1564 PCOR(pcop)->r->wasUsed=1;
1565 PCOR(pcop)->r->isFree=0;
1567 /* push value on stack */
1568 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1576 /*-----------------------------------------------------------------*/
1577 /* pic16_popGetTempRegCond - create a new temporary pCodeOp, but */
1578 /* don't save if inside v */
1579 /*-----------------------------------------------------------------*/
1580 pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock)
1585 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1588 // werror(W_POSSBUG2, __FILE__, __LINE__);
1591 _TempReg_lock += lock;
1596 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1597 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1598 PCOR(pcop)->r->wasUsed=1;
1599 PCOR(pcop)->r->isFree=0;
1601 if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) {
1602 /* push value on stack */
1603 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1613 /*-----------------------------------------------------------------*/
1614 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1615 /*-----------------------------------------------------------------*/
1616 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1618 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1620 _TempReg_lock -= lock;
1622 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1623 PCOR(pcop)->r->isFree = 1;
1624 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1627 /*-----------------------------------------------------------------*/
1628 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1629 /*-----------------------------------------------------------------*/
1630 pCodeOp *pic16_popGetLabel(unsigned int key)
1633 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1638 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1641 /*-----------------------------------------------------------------*/
1642 /* pic16_popCopyReg - copy a pcode operator */
1643 /*-----------------------------------------------------------------*/
1644 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1648 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1649 pcor->pcop.type = pc->pcop.type;
1651 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1652 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1654 pcor->pcop.name = NULL;
1657 pcor->rIdx = pc->rIdx;
1660 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1665 /*-----------------------------------------------------------------*/
1666 /* pic16_popGetLit - asm operator to pcode operator conversion */
1667 /*-----------------------------------------------------------------*/
1668 pCodeOp *pic16_popGetLit(int lit)
1670 return pic16_newpCodeOpLit(lit);
1673 /*-----------------------------------------------------------------*/
1674 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1675 /*-----------------------------------------------------------------*/
1676 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1678 return pic16_newpCodeOpLit2(lit, arg2);
1682 /*-----------------------------------------------------------------*/
1683 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1684 /*-----------------------------------------------------------------*/
1685 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1687 return pic16_newpCodeOpImmd(name, offset,index, 0);
1691 /*-----------------------------------------------------------------*/
1692 /* pic16_popGet - asm operator to pcode operator conversion */
1693 /*-----------------------------------------------------------------*/
1694 pCodeOp *pic16_popGetWithString(char *str)
1700 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1704 pcop = pic16_newpCodeOp(str,PO_STR);
1709 /*-----------------------------------------------------------------*/
1710 /* pic16_popRegFromString - */
1711 /*-----------------------------------------------------------------*/
1712 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1715 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1716 pcop->type = PO_DIR;
1718 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1719 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1724 pcop->name = Safe_calloc(1,strlen(str)+1);
1725 strcpy(pcop->name,str);
1727 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1729 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1731 /* make sure that register doesn't exist,
1732 * and operand isn't NULL
1733 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1734 if((PCOR(pcop)->r == NULL)
1736 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1737 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1738 // __FUNCTION__, __LINE__, str, size, offset);
1740 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1741 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1744 PCOR(pcop)->instance = offset;
1749 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1753 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1755 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1756 PCOR(pcop)->rIdx = rIdx;
1757 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1759 PCOR(pcop)->r->isFree = 0;
1760 PCOR(pcop)->r->wasUsed = 1;
1762 pcop->type = PCOR(pcop)->r->pc_type;
1767 /*---------------------------------------------------------------------------------*/
1768 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1770 /*---------------------------------------------------------------------------------*/
1771 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1776 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1778 /* comment the following check, so errors to throw up */
1779 // if(!pcop2)return NULL;
1781 temp = pic16_popGet(aop_dst, offset);
1782 pcop2->pcop2 = temp;
1789 /*--------------------------------------------------------------------------------.-*/
1790 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1791 /* VR 030601 , adapted by Hans Dorn */
1792 /*--------------------------------------------------------------------------------.-*/
1793 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1797 pcop2 = (pCodeOpReg2 *)src;
1805 /*---------------------------------------------------------------------------------*/
1806 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1807 /* movff instruction */
1808 /*---------------------------------------------------------------------------------*/
1809 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1814 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1815 pcop2->pcop2 = pic16_popCopyReg(dst);
1817 /* the pCodeOp may be already allocated */
1818 pcop2 = (pCodeOpReg2 *)(src);
1819 pcop2->pcop2 = (pCodeOp *)(dst);
1826 /*-----------------------------------------------------------------*/
1827 /* pic16_popGet - asm operator to pcode operator conversion */
1828 /*-----------------------------------------------------------------*/
1829 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1831 //char *s = buffer ;
1836 /* offset is greater than
1839 // if (offset > (aop->size - 1) &&
1840 // aop->type != AOP_LIT)
1841 // return NULL; //zero;
1843 /* depending on type */
1844 switch (aop->type) {
1850 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1851 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1858 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1859 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
1860 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1861 PCOR(pcop)->r->wasUsed = 1;
1862 PCOR(pcop)->r->isFree = 0;
1864 PCOR(pcop)->instance = offset;
1865 pcop->type = PCOR(pcop)->r->pc_type;
1869 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1870 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1873 /* pCodeOp is already allocated from aopForSym */
1874 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1875 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1881 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1883 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1885 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1887 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1888 PCOR(pcop)->rIdx = rIdx;
1889 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1890 PCOR(pcop)->r->wasUsed=1;
1891 PCOR(pcop)->r->isFree=0;
1893 PCOR(pcop)->instance = offset;
1894 pcop->type = PCOR(pcop)->r->pc_type;
1895 // rs = aop->aopu.aop_reg[offset]->name;
1896 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1900 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1901 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1907 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1908 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1913 assert (aop && aop->aopu.aop_reg[offset] != NULL);
1914 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1916 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1918 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1919 // pcop->type = PO_GPR_REGISTER;
1920 PCOR(pcop)->rIdx = rIdx;
1921 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
1922 PCOR(pcop)->r->wasUsed=1;
1923 PCOR(pcop)->r->isFree=0;
1925 PCOR(pcop)->instance = offset;
1926 pcop->type = PCOR(pcop)->r->pc_type;
1928 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type));
1929 rs = aop->aopu.aop_reg[offset]->name;
1930 DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1935 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1937 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1938 PCOR(pcop)->instance = offset;
1939 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1940 //if(PCOR(pcop)->r == NULL)
1941 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1945 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1946 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1949 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1950 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1953 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1954 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1955 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1956 pcop->type = PCOR(pcop)->r->pc_type;
1957 pcop->name = PCOR(pcop)->r->name;
1963 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1965 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1966 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1968 switch( aop->aopu.pcop->type ) {
1969 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1970 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1972 assert( 0 ); /* should never reach here */;
1975 PCOI(pcop)->offset = offset;
1980 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1981 "pic16_popGet got unsupported aop->type");
1984 /*-----------------------------------------------------------------*/
1985 /* pic16_aopPut - puts a string for a aop */
1986 /*-----------------------------------------------------------------*/
1987 void pic16_aopPut (asmop *aop, char *s, int offset)
1994 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1996 if (aop->size && offset > ( aop->size - 1)) {
1997 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1998 "pic16_aopPut got offset > aop->size");
2002 /* will assign value to value */
2003 /* depending on where it is ofcourse */
2004 switch (aop->type) {
2007 sprintf(d,"(%s + %d)",
2008 aop->aopu.aop_dir,offset);
2009 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2012 sprintf(d,"%s",aop->aopu.aop_dir);
2015 DEBUGpic16_emitcode(";","%d",__LINE__);
2017 pic16_emitcode("movf","%s,w",s);
2018 pic16_emitcode("movwf","%s",d);
2021 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2022 if(offset >= aop->size) {
2023 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2026 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2029 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2036 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2037 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2040 strcmp(s,"r0") == 0 ||
2041 strcmp(s,"r1") == 0 ||
2042 strcmp(s,"r2") == 0 ||
2043 strcmp(s,"r3") == 0 ||
2044 strcmp(s,"r4") == 0 ||
2045 strcmp(s,"r5") == 0 ||
2046 strcmp(s,"r6") == 0 ||
2047 strcmp(s,"r7") == 0 )
2048 pic16_emitcode("mov","%s,%s ; %d",
2049 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2053 if(strcmp(s,"W")==0 )
2054 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2056 pic16_emitcode("movwf","%s",
2057 aop->aopu.aop_reg[offset]->name);
2059 if(strcmp(s,zero)==0) {
2060 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2062 } else if(strcmp(s,"W")==0) {
2063 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2064 pcop->type = PO_GPR_REGISTER;
2066 PCOR(pcop)->rIdx = -1;
2067 PCOR(pcop)->r = NULL;
2069 DEBUGpic16_emitcode(";","%d",__LINE__);
2070 pcop->name = Safe_strdup(s);
2071 pic16_emitpcode(POC_MOVFW,pcop);
2072 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2073 } else if(strcmp(s,one)==0) {
2074 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2075 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2077 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2085 if (aop->type == AOP_DPTR2)
2091 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2092 "pic16_aopPut writting to code space");
2096 while (offset > aop->coff) {
2098 pic16_emitcode ("inc","dptr");
2101 while (offset < aop->coff) {
2103 pic16_emitcode("lcall","__decdptr");
2108 /* if not in accumulater */
2111 pic16_emitcode ("movx","@dptr,a");
2113 if (aop->type == AOP_DPTR2)
2121 while (offset > aop->coff) {
2123 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2125 while (offset < aop->coff) {
2127 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2133 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2138 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2140 if (strcmp(s,"r0") == 0 ||
2141 strcmp(s,"r1") == 0 ||
2142 strcmp(s,"r2") == 0 ||
2143 strcmp(s,"r3") == 0 ||
2144 strcmp(s,"r4") == 0 ||
2145 strcmp(s,"r5") == 0 ||
2146 strcmp(s,"r6") == 0 ||
2147 strcmp(s,"r7") == 0 ) {
2149 sprintf(buffer,"a%s",s);
2150 pic16_emitcode("mov","@%s,%s",
2151 aop->aopu.aop_ptr->name,buffer);
2153 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2158 if (strcmp(s,"a") == 0)
2159 pic16_emitcode("push","acc");
2161 pic16_emitcode("push","%s",s);
2166 /* if bit variable */
2167 if (!aop->aopu.aop_dir) {
2168 pic16_emitcode("clr","a");
2169 pic16_emitcode("rlc","a");
2172 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2175 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2178 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2180 lbl = newiTempLabel(NULL);
2182 if (strcmp(s,"a")) {
2185 pic16_emitcode("clr","c");
2186 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2187 pic16_emitcode("cpl","c");
2188 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2189 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2196 if (strcmp(aop->aopu.aop_str[offset],s))
2197 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2202 if (!offset && (strcmp(s,"acc") == 0))
2205 if (strcmp(aop->aopu.aop_str[offset],s))
2206 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2210 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2211 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2212 // "pic16_aopPut got unsupported aop->type");
2218 /*-----------------------------------------------------------------*/
2219 /* mov2w - generate either a MOVLW or MOVFW based operand type */
2220 /*-----------------------------------------------------------------*/
2221 void mov2w (asmop *aop, int offset)
2223 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2226 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2228 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2231 static void mov2f(asmop *dst, asmop *src, int offset)
2233 if(is_LitAOp(src)) {
2234 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2235 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2237 if(pic16_sameRegsOfs(src, dst, offset))return;
2238 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2239 pic16_popGet(dst, offset)));
2243 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2245 if(is_LitAOp(src)) {
2246 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2247 pic16_emitpcode(POC_MOVWF, dst);
2249 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2253 void pic16_testStackOverflow(void)
2255 #define GSTACK_TEST_NAME "__gstack_test"
2257 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2262 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2263 strcpy(sym->rname, GSTACK_TEST_NAME);
2264 checkAddSym(&externs, sym);
2269 /* push pcop into stack */
2270 void pic16_pushpCodeOp(pCodeOp *pcop)
2272 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2273 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2274 if(pic16_options.gstack)
2275 pic16_testStackOverflow();
2279 /* pop pcop from stack */
2280 void pic16_poppCodeOp(pCodeOp *pcop)
2282 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2283 if(pic16_options.gstack)
2284 pic16_testStackOverflow();
2288 /*-----------------------------------------------------------------*/
2289 /* pushw - pushes wreg to stack */
2290 /*-----------------------------------------------------------------*/
2293 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2294 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2295 if(pic16_options.gstack)
2296 pic16_testStackOverflow();
2300 /*-----------------------------------------------------------------*/
2301 /* pushaop - pushes aop to stack */
2302 /*-----------------------------------------------------------------*/
2303 void pushaop(asmop *aop, int offset)
2305 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2307 if(is_LitAOp(aop)) {
2308 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2309 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2311 pic16_emitpcode(POC_MOVFF,
2312 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg(&pic16_pc_postdec1)));
2315 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2316 if(pic16_options.gstack)
2317 pic16_testStackOverflow();
2320 /*-----------------------------------------------------------------*/
2321 /* popaop - pops aop from stack */
2322 /*-----------------------------------------------------------------*/
2323 void popaop(asmop *aop, int offset)
2325 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2326 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2327 if(pic16_options.gstack)
2328 pic16_testStackOverflow();
2331 void popaopidx(asmop *aop, int offset, int index)
2335 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2337 if(STACK_MODEL_LARGE)ofs++;
2339 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2340 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2341 if(pic16_options.gstack)
2342 pic16_testStackOverflow();
2345 /*-----------------------------------------------------------------*/
2346 /* reAdjustPreg - points a register back to where it should */
2347 /*-----------------------------------------------------------------*/
2348 static void reAdjustPreg (asmop *aop)
2352 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2354 if ((size = aop->size) <= 1)
2357 switch (aop->type) {
2361 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2365 if (aop->type == AOP_DPTR2)
2371 pic16_emitcode("lcall","__decdptr");
2374 if (aop->type == AOP_DPTR2)
2386 /*-----------------------------------------------------------------*/
2387 /* opIsGptr: returns non-zero if the passed operand is */
2388 /* a generic pointer type. */
2389 /*-----------------------------------------------------------------*/
2390 static int opIsGptr(operand *op)
2392 sym_link *type = operandType(op);
2394 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2395 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2403 /*-----------------------------------------------------------------*/
2404 /* pic16_getDataSize - get the operand data size */
2405 /*-----------------------------------------------------------------*/
2406 int pic16_getDataSize(operand *op)
2408 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2411 return AOP_SIZE(op);
2413 // tsd- in the pic port, the genptr size is 1, so this code here
2414 // fails. ( in the 8051 port, the size was 4).
2417 size = AOP_SIZE(op);
2418 if (size == GPTRSIZE)
2420 sym_link *type = operandType(op);
2421 if (IS_GENPTR(type))
2423 /* generic pointer; arithmetic operations
2424 * should ignore the high byte (pointer type).
2427 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2434 /*-----------------------------------------------------------------*/
2435 /* pic16_outAcc - output Acc */
2436 /*-----------------------------------------------------------------*/
2437 void pic16_outAcc(operand *result)
2440 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2441 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2444 size = pic16_getDataSize(result);
2446 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2449 /* unsigned or positive */
2451 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2456 /*-----------------------------------------------------------------*/
2457 /* pic16_outBitC - output a bit C */
2458 /* Move to result the value of Carry flag -- VR */
2459 /*-----------------------------------------------------------------*/
2460 void pic16_outBitC(operand *result)
2464 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2466 /* if the result is bit */
2467 if (AOP_TYPE(result) == AOP_CRY) {
2468 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2469 pic16_aopPut(AOP(result),"c",0);
2472 i = AOP_SIZE(result);
2474 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2476 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2480 /*-----------------------------------------------------------------*/
2481 /* pic16_outBitOp - output a bit from Op */
2482 /* Move to result the value of set/clr op -- VR */
2483 /*-----------------------------------------------------------------*/
2484 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2488 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2490 /* if the result is bit */
2491 if (AOP_TYPE(result) == AOP_CRY) {
2492 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2493 pic16_aopPut(AOP(result),"c",0);
2496 i = AOP_SIZE(result);
2498 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2500 pic16_emitpcode(POC_RRCF, pcop);
2501 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2505 /*-----------------------------------------------------------------*/
2506 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2507 /*-----------------------------------------------------------------*/
2508 void pic16_toBoolean(operand *oper)
2510 int size = AOP_SIZE(oper) - 1;
2513 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2515 if ( AOP_TYPE(oper) != AOP_ACC) {
2516 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2519 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2524 #if !defined(GEN_Not)
2525 /*-----------------------------------------------------------------*/
2526 /* genNot - generate code for ! operation */
2527 /*-----------------------------------------------------------------*/
2528 static void pic16_genNot (iCode *ic)
2534 /* assign asmOps to operand & result */
2535 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2536 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2538 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2539 /* if in bit space then a special case */
2540 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2541 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2542 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2543 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2545 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2546 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2547 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2552 size = AOP_SIZE(IC_LEFT(ic));
2554 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2555 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2556 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2559 pic16_toBoolean(IC_LEFT(ic));
2561 tlbl = newiTempLabel(NULL);
2562 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2563 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2564 pic16_outBitC(IC_RESULT(ic));
2567 /* release the aops */
2568 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2569 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2574 #if !defined(GEN_Cpl)
2575 /*-----------------------------------------------------------------*/
2576 /* genCpl - generate code for complement */
2577 /*-----------------------------------------------------------------*/
2578 static void pic16_genCpl (iCode *ic)
2584 /* assign asmOps to operand & result */
2585 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2586 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2588 /* if both are in bit space then
2590 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2591 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2593 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2594 pic16_emitcode("cpl","c");
2595 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2599 size = AOP_SIZE(IC_RESULT(ic));
2602 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2604 pic16_emitcode("cpl","a");
2605 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2607 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2608 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2610 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2611 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2619 /* release the aops */
2620 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2621 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2625 /*-----------------------------------------------------------------*/
2626 /* genUminusFloat - unary minus for floating points */
2627 /*-----------------------------------------------------------------*/
2628 static void genUminusFloat(operand *op,operand *result)
2630 int size ,offset =0 ;
2633 /* for this we just need to flip the
2634 first it then copy the rest in place */
2635 size = AOP_SIZE(op);
2638 mov2f(AOP(result), AOP(op), offset);
2642 /* toggle the MSB's highest bit */
2643 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2646 /*-----------------------------------------------------------------*/
2647 /* genUminus - unary minus code generation */
2648 /*-----------------------------------------------------------------*/
2649 static void genUminus (iCode *ic)
2652 sym_link *optype, *rtype;
2657 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2658 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2660 /* if both in bit space then special case */
2661 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2662 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2664 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2665 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2666 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2670 optype = operandType(IC_LEFT(ic));
2671 rtype = operandType(IC_RESULT(ic));
2673 /* if float then do float stuff */
2674 if (IS_FLOAT(optype)) {
2675 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2679 /* otherwise subtract from zero by taking the 2's complement */
2680 size = AOP_SIZE(IC_LEFT(ic));
2682 for(i=0; i<size; i++) {
2683 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2684 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)),i));
2686 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2687 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2691 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2692 for(i=1; i<size; i++) {
2694 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2698 /* release the aops */
2699 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2700 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2704 /*-----------------------------------------------------------------*/
2705 /* saveRegisters - will look for a call and save the registers */
2706 /*-----------------------------------------------------------------*/
2707 static void saveRegisters(iCode *lic)
2714 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2716 for (ic = lic ; ic ; ic = ic->next)
2717 if (ic->op == CALL || ic->op == PCALL)
2721 fprintf(stderr,"found parameter push with no function call\n");
2725 /* if the registers have been saved already then
2727 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2730 /* find the registers in use at this time
2731 and push them away to safety */
2732 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2736 if (options.useXstack) {
2737 if (bitVectBitValue(rsave,R0_IDX))
2738 pic16_emitcode("mov","b,r0");
2739 pic16_emitcode("mov","r0,%s",spname);
2740 for (i = 0 ; i < pic16_nRegs ; i++) {
2741 if (bitVectBitValue(rsave,i)) {
2743 pic16_emitcode("mov","a,b");
2745 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2746 pic16_emitcode("movx","@r0,a");
2747 pic16_emitcode("inc","r0");
2750 pic16_emitcode("mov","%s,r0",spname);
2751 if (bitVectBitValue(rsave,R0_IDX))
2752 pic16_emitcode("mov","r0,b");
2754 //for (i = 0 ; i < pic16_nRegs ; i++) {
2755 // if (bitVectBitValue(rsave,i))
2756 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2759 dtype = operandType(IC_LEFT(ic));
2760 if (currFunc && dtype &&
2761 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2762 IFFUNC_ISISR(currFunc->type) &&
2765 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2768 /*-----------------------------------------------------------------*/
2769 /* unsaveRegisters - pop the pushed registers */
2770 /*-----------------------------------------------------------------*/
2771 static void unsaveRegisters (iCode *ic)
2776 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2777 /* find the registers in use at this time
2778 and push them away to safety */
2779 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2782 if (options.useXstack) {
2783 pic16_emitcode("mov","r0,%s",spname);
2784 for (i = pic16_nRegs ; i >= 0 ; i--) {
2785 if (bitVectBitValue(rsave,i)) {
2786 pic16_emitcode("dec","r0");
2787 pic16_emitcode("movx","a,@r0");
2789 pic16_emitcode("mov","b,a");
2791 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2795 pic16_emitcode("mov","%s,r0",spname);
2796 if (bitVectBitValue(rsave,R0_IDX))
2797 pic16_emitcode("mov","r0,b");
2799 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2800 // if (bitVectBitValue(rsave,i))
2801 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2808 /*-----------------------------------------------------------------*/
2810 /*-----------------------------------------------------------------*/
2811 static void pushSide(operand * oper, int size)
2814 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2816 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2817 if (AOP_TYPE(oper) != AOP_REG &&
2818 AOP_TYPE(oper) != AOP_DIR &&
2820 pic16_emitcode("mov","a,%s",l);
2821 pic16_emitcode("push","acc");
2823 pic16_emitcode("push","%s",l);
2828 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2830 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2831 pic16_emitpcode(POC_MOVFW, src);
2832 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2834 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2835 src, pic16_popGet(AOP(op), offset)));
2840 /*-----------------------------------------------------------------*/
2841 /* assignResultValue - assign results to oper, rescall==1 is */
2842 /* called from genCall() or genPcall() */
2843 /*-----------------------------------------------------------------*/
2844 static void assignResultValue(operand * oper, int rescall)
2846 int size = AOP_SIZE(oper);
2850 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2851 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2854 /* assign result from a call/pcall function() */
2856 /* function results are stored in a special order,
2857 * see top of file with Function return policy, or manual */
2860 /* 8-bits, result in WREG */
2861 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2864 /* 16-bits, result in PRODL:WREG */
2865 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2869 /* 24-bits, result in PRODH:PRODL:WREG */
2870 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2874 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2875 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2879 /* >32-bits, result on stack, and FSR0 points to beginning.
2880 * Fix stack when done */
2882 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2884 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2885 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2887 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2892 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2893 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2894 if(STACK_MODEL_LARGE) {
2896 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2900 int areg = 0; /* matching argument register */
2902 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2903 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2906 /* its called from genReceive (probably) -- VR */
2907 /* I hope this code will not be called from somewhere else in the future!
2908 * We manually set the pseudo stack pointer in genReceive. - dw
2910 if(!GpsuedoStkPtr && _G.useWreg) {
2911 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2913 /* The last byte in the assignment is in W */
2914 if(areg <= GpsuedoStkPtr) {
2916 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2918 // debugf("receive from WREG\n", 0);
2920 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2923 _G.stack_lat = AOP_SIZE(oper)-1;
2928 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2929 // debugf("receive from STACK\n", 0);
2936 /*-----------------------------------------------------------------*/
2937 /* genIpush - generate code for pushing this gets a little complex */
2938 /*-----------------------------------------------------------------*/
2939 static void genIpush (iCode *ic)
2941 // int size, offset=0;
2944 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2947 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2949 /* send to stack as normal */
2950 addSet(&_G.sendSet,ic);
2951 // addSetHead(&_G.sendSet,ic);
2952 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2957 int size, offset = 0 ;
2961 /* if this is not a parm push : ie. it is spill push
2962 and spill push is always done on the local stack */
2963 if (!ic->parmPush) {
2965 /* and the item is spilt then do nothing */
2966 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2969 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2970 size = AOP_SIZE(IC_LEFT(ic));
2971 /* push it on the stack */
2973 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2978 pic16_emitcode("push","%s",l);
2983 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2987 /*-----------------------------------------------------------------*/
2988 /* genIpop - recover the registers: can happen only for spilling */
2989 /*-----------------------------------------------------------------*/
2990 static void genIpop (iCode *ic)
2993 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2998 /* if the temp was not pushed then */
2999 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3002 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3003 size = AOP_SIZE(IC_LEFT(ic));
3006 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3009 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3014 /*-----------------------------------------------------------------*/
3015 /* unsaverbank - restores the resgister bank from stack */
3016 /*-----------------------------------------------------------------*/
3017 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3019 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3025 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3027 if (options.useXstack) {
3029 r = getFreePtr(ic,&aop,FALSE);
3032 pic16_emitcode("mov","%s,_spx",r->name);
3033 pic16_emitcode("movx","a,@%s",r->name);
3034 pic16_emitcode("mov","psw,a");
3035 pic16_emitcode("dec","%s",r->name);
3038 pic16_emitcode ("pop","psw");
3041 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3042 if (options.useXstack) {
3043 pic16_emitcode("movx","a,@%s",r->name);
3044 //pic16_emitcode("mov","(%s+%d),a",
3045 // regspic16[i].base,8*bank+regspic16[i].offset);
3046 pic16_emitcode("dec","%s",r->name);
3049 pic16_emitcode("pop",""); //"(%s+%d)",
3050 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3053 if (options.useXstack) {
3055 pic16_emitcode("mov","_spx,%s",r->name);
3056 pic16_freeAsmop(NULL,aop,ic,TRUE);
3062 /*-----------------------------------------------------------------*/
3063 /* saverbank - saves an entire register bank on the stack */
3064 /*-----------------------------------------------------------------*/
3065 static void saverbank (int bank, iCode *ic, bool pushPsw)
3067 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3073 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3074 if (options.useXstack) {
3077 r = getFreePtr(ic,&aop,FALSE);
3078 pic16_emitcode("mov","%s,_spx",r->name);
3082 for (i = 0 ; i < pic16_nRegs ;i++) {
3083 if (options.useXstack) {
3084 pic16_emitcode("inc","%s",r->name);
3085 //pic16_emitcode("mov","a,(%s+%d)",
3086 // regspic16[i].base,8*bank+regspic16[i].offset);
3087 pic16_emitcode("movx","@%s,a",r->name);
3089 pic16_emitcode("push","");// "(%s+%d)",
3090 //regspic16[i].base,8*bank+regspic16[i].offset);
3094 if (options.useXstack) {
3095 pic16_emitcode("mov","a,psw");
3096 pic16_emitcode("movx","@%s,a",r->name);
3097 pic16_emitcode("inc","%s",r->name);
3098 pic16_emitcode("mov","_spx,%s",r->name);
3099 pic16_freeAsmop (NULL,aop,ic,TRUE);
3102 pic16_emitcode("push","psw");
3104 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3112 static int wparamCmp(void *p1, void *p2)
3114 return (!strcmp((char *)p1, (char *)p2));
3117 int inWparamList(char *s)
3119 return isinSetWith(wparamList, s, wparamCmp);
3123 /*-----------------------------------------------------------------*/
3124 /* genCall - generates a call statement */
3125 /*-----------------------------------------------------------------*/
3126 static void genCall (iCode *ic)
3136 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3137 /* if caller saves & we have not saved then */
3138 // if (!ic->regsSaved)
3139 // saveRegisters(ic);
3141 /* initialise stackParms for IPUSH pushes */
3142 // stackParms = psuedoStkPtr;
3143 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3144 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3145 inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
3148 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3151 /* if send set is not empty the assign */
3154 int psuedoStkPtr=-1;
3155 int firstTimeThruLoop = 1;
3158 /* reverse sendSet if function is not reentrant */
3159 if(!IFFUNC_ISREENT(ftype))
3160 _G.sendSet = reverseSet(_G.sendSet);
3162 /* First figure how many parameters are getting passed */
3166 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3170 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3171 size = AOP_SIZE(IC_LEFT(sic));
3175 /* pass the last byte through WREG */
3179 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3180 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3181 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3183 if(!firstTimeThruLoop) {
3184 /* If this is not the first time we've been through the loop
3185 * then we need to save the parameter in a temporary
3186 * register. The last byte of the last parameter is
3190 // --psuedoStkPtr; // sanity check
3194 firstTimeThruLoop=0;
3196 mov2w (AOP(IC_LEFT(sic)), size);
3201 /* all arguments are passed via stack */
3205 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3206 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3207 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3209 // pushaop(AOP(IC_LEFT(sic)), size);
3210 mov2w (AOP(IC_LEFT(sic)), size);
3215 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3219 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3220 pushw(); /* save last parameter to stack if functions has varargs */
3224 } else use_wreg = 0;
3226 _G.stackRegSet = _G.sendSet;
3231 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3235 /* if we need to assign a result value */
3236 if ((IS_ITEMP(IC_RESULT(ic))
3237 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3238 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3239 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3242 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3245 assignResultValue(IC_RESULT(ic), 1);
3247 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3248 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3250 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3253 if(!stackParms && ic->parmBytes) {
3254 stackParms = ic->parmBytes;
3257 stackParms -= use_wreg;
3260 if(stackParms == 1) {
3261 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1l));
3263 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3264 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3266 if(STACK_MODEL_LARGE) {
3268 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3273 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3276 /* adjust the stack for parameters if required */
3277 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3280 /* if register bank was saved then pop them */
3282 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3284 /* if we hade saved some registers then unsave them */
3285 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3286 unsaveRegisters (ic);
3292 /*-----------------------------------------------------------------*/
3293 /* genPcall - generates a call by pointer statement */
3294 /* new version, created from genCall - HJD */
3295 /*-----------------------------------------------------------------*/
3296 static void genPcall (iCode *ic)
3298 sym_link *ftype, *fntype;
3300 symbol *retlbl = newiTempLabel(NULL);
3301 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3305 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3306 fntype = operandType( IC_LEFT(ic) )->next;
3308 /* if send set is not empty the assign */
3311 int psuedoStkPtr=-1;
3313 /* reverse sendSet if function is not reentrant */
3314 if(!IFFUNC_ISREENT(fntype))
3315 _G.sendSet = reverseSet(_G.sendSet);
3319 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3322 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3323 size = AOP_SIZE(IC_LEFT(sic));
3326 /* all parameters are passed via stack, since WREG is clobbered
3327 * by the calling sequence */
3329 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3330 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3331 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3333 mov2w (AOP(IC_LEFT(sic)), size);
3337 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3340 _G.stackRegSet = _G.sendSet;
3344 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3346 // push return address
3347 // push $ on return stack, then replace with retlbl
3349 pic16_emitpcodeNULLop(POC_PUSH);
3351 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3352 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3353 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3354 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3355 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3356 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3358 /* make the call by writing the pointer into pc */
3359 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3360 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3362 // note: MOVFF to PCL not allowed
3363 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3364 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3367 /* return address is here: (X) */
3368 pic16_emitpLabelFORCE(retlbl->key);
3370 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3373 /* if we need assign a result value */
3374 if ((IS_ITEMP(IC_RESULT(ic))
3375 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3376 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3377 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3380 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3383 assignResultValue(IC_RESULT(ic), 1);
3385 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3386 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3388 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3391 // stackParms -= use_wreg;
3394 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3395 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3396 if(STACK_MODEL_LARGE) {
3397 /* this implies that stackParms < 256 !!! -- VR */
3399 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3404 /*-----------------------------------------------------------------*/
3405 /* resultRemat - result is rematerializable */
3406 /*-----------------------------------------------------------------*/
3407 static int resultRemat (iCode *ic)
3409 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3410 if (SKIP_IC(ic) || ic->op == IFX)
3413 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3414 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3415 if (sym->remat && !POINTER_SET(ic))
3422 #if defined(__BORLANDC__) || defined(_MSC_VER)
3423 #define STRCASECMP stricmp
3425 #define STRCASECMP strcasecmp
3429 /*-----------------------------------------------------------------*/
3430 /* inExcludeList - return 1 if the string is in exclude Reg list */
3431 /*-----------------------------------------------------------------*/
3432 static bool inExcludeList(char *s)
3434 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3437 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3438 if (options.excludeRegs[i] &&
3439 STRCASECMP(options.excludeRegs[i],"none") == 0)
3442 for ( i = 0 ; options.excludeRegs[i]; i++) {
3443 if (options.excludeRegs[i] &&
3444 STRCASECMP(s,options.excludeRegs[i]) == 0)
3451 /*-----------------------------------------------------------------*/
3452 /* genFunction - generated code for function entry */
3453 /*-----------------------------------------------------------------*/
3454 static void genFunction (iCode *ic)
3460 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3462 pic16_labelOffset += (max_key+4);
3467 ftype = operandType(IC_LEFT(ic));
3468 sym = OP_SYMBOL(IC_LEFT(ic));
3470 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3471 /* create an absolute section at the interrupt vector:
3472 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3480 sym = OP_SYMBOL( IC_LEFT(ic));
3482 if(interrupts[i]->name
3483 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3490 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3491 __FILE__, __LINE__, sym->name);
3494 _G.interruptvector = found;
3497 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3498 asym = newSymbol(asymname, 0);
3500 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3501 pic16_addpBlock( apb );
3503 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3504 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3505 pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3507 /* mark the end of this tiny function */
3508 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3513 abSym = Safe_calloc(1, sizeof(absSym));
3514 strcpy(abSym->name, asymname);
3516 switch( _G.interruptvector ) {
3517 case 0: abSym->address = 0x000000; break;
3518 case 1: abSym->address = 0x000008; break;
3519 case 2: abSym->address = 0x000018; break;
3522 /* relocate interrupt vectors if needed */
3523 abSym->address += pic16_options.ivt_loc;
3525 addSet(&absSymSet, abSym);
3529 /* create the function header */
3530 pic16_emitcode(";","-----------------------------------------");
3531 pic16_emitcode(";"," function %s",sym->name);
3532 pic16_emitcode(";","-----------------------------------------");
3534 pic16_emitcode("","%s:",sym->rname);
3535 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3541 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3542 if(!strcmp(ab->name, sym->rname)) {
3543 pic16_pBlockConvert2Absolute(pb);
3550 if(IFFUNC_ISNAKED(ftype)) {
3551 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3555 /* if critical function then turn interrupts off */
3556 if (IFFUNC_ISCRITICAL(ftype)) {
3557 //pic16_emitcode("clr","ea");
3560 _G.fregsUsed = sym->regsUsed;
3562 /* if this is an interrupt service routine then
3563 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3564 if (IFFUNC_ISISR(sym->type)) {
3565 _G.usefastretfie = 1; /* use shadow registers by default */
3567 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3568 if(!(_G.interruptvector == 1)) {
3569 /* do not save WREG,STATUS,BSR for high priority interrupts
3570 * because they are stored in the hardware shadow registers already */
3571 _G.usefastretfie = 0;
3572 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3573 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3574 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3577 /* these should really be optimized somehow, because not all
3578 * interrupt handlers modify them */
3579 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3580 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3581 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3582 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3584 // pic16_pBlockConvert2ISR(pb);
3588 /* emit code to setup stack frame if user enabled,
3589 * and function is not main() */
3591 //fprintf(stderr, "function name: %s\n", sym->name);
3592 if(strcmp(sym->name, "main")) {
3593 if(1 /*!options.ommitFramePtr || sym->regsUsed*/) {
3594 /* setup the stack frame */
3595 if(STACK_MODEL_LARGE)
3596 pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2h));
3597 pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2l));
3598 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3599 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3600 if(STACK_MODEL_LARGE)
3601 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3605 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3608 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3610 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3611 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3613 pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_fsr1h));
3616 if(inWparamList(sym->name)) {
3617 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3624 /* if callee-save to be used for this function
3625 * then save the registers being used in this function */
3626 // if (IFFUNC_CALLEESAVES(sym->type))
3630 /* if any registers used */
3631 if (sym->regsUsed) {
3632 /* save the registers used */
3633 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3634 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3635 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3636 if (bitVectBitValue(sym->regsUsed,i)) {
3637 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3640 if(!pic16_regWithIdx(i)->wasUsed) {
3641 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3642 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3643 pic16_regWithIdx(i)->wasUsed = 1;
3647 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3651 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3652 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3655 /*-----------------------------------------------------------------*/
3656 /* genEndFunction - generates epilogue for functions */
3657 /*-----------------------------------------------------------------*/
3658 static void genEndFunction (iCode *ic)
3660 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3664 if(IFFUNC_ISNAKED(sym->type)) {
3665 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3671 /* add code for ISCRITICAL */
3672 if(IFFUNC_ISCRITICAL(sym->type)) {
3673 /* if critical function, turn on interrupts */
3675 /* TODO: add code here -- VR */
3678 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3680 if (sym->stack == 1) {
3681 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg(&pic16_pc_fsr1l));
3682 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3684 // we have to add more than one...
3685 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc1)); // this holds a return value!
3686 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3687 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l));
3689 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h));
3690 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3691 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_plusw1)); // this holds a retrun value!
3695 // sym->regsUsed = _G.fregsUsed;
3697 /* now we need to restore the registers */
3698 /* if any registers used */
3699 if (sym->regsUsed) {
3702 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3703 /* restore registers used */
3704 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3705 for ( i = sym->regsUsed->size; i >= 0; i--) {
3706 if (bitVectBitValue(sym->regsUsed,i)) {
3707 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3711 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3715 if(strcmp(sym->name, "main")) {
3716 if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) {
3717 /* restore stack frame */
3718 if(STACK_MODEL_LARGE)
3719 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2h ));
3720 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3721 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2l ));
3722 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3728 if (IFFUNC_ISISR(sym->type)) {
3729 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3730 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3731 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3732 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3734 if(!(_G.interruptvector == 1)) {
3735 /* do not restore interrupt vector for WREG,STATUS,BSR
3736 * for high priority interrupt, see genFunction */
3737 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3738 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3739 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3741 _G.interruptvector = 0; /* sanity check */
3744 /* if debug then send end of function */
3745 /* if (options.debug && currFunc) */
3747 debugFile->writeEndFunction (currFunc, ic, 1);
3750 if(_G.usefastretfie)
3751 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3753 pic16_emitpcodeNULLop(POC_RETFIE);
3755 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3757 _G.usefastretfie = 0;
3761 if (IFFUNC_ISCRITICAL(sym->type)) {
3762 pic16_emitcode("setb","ea");
3765 /* if debug then send end of function */
3767 debugFile->writeEndFunction (currFunc, ic, 1);
3770 /* insert code to restore stack frame, if user enabled it
3771 * and function is not main() */
3774 pic16_emitpcodeNULLop(POC_RETURN);
3776 /* Mark the end of a function */
3777 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3781 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3784 unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3786 pic16_emitpcode(POC_CLRF, dest);
3788 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3789 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3792 if(dest->type == PO_WREG && (offset == 0)) {
3793 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3796 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3800 /*-----------------------------------------------------------------*/
3801 /* genRet - generate code for return statement */
3802 /*-----------------------------------------------------------------*/
3803 static void genRet (iCode *ic)
3809 /* if we have no return value then
3810 * just generate the "ret" */
3815 /* we have something to return then
3816 * move the return value into place */
3817 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3818 size = AOP_SIZE(IC_LEFT(ic));
3822 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3823 // pic16_emitpcode(POC_MOVFF,
3824 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3827 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3828 // pic16_emitpcode(POC_MOVFF,
3829 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3832 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3833 // pic16_emitpcode(POC_MOVFF,
3834 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3837 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3839 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3840 // pic16_emitpcode(POC_MOVFF,
3841 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3844 /* >32-bits, setup stack and FSR0 */
3846 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3847 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3849 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3851 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3856 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3857 pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3859 if(STACK_MODEL_LARGE) {
3860 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3861 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3863 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3868 /* old code, left here for reference -- VR */
3872 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3874 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3875 pic16_emitpcomment("push %s",l);
3878 DEBUGpic16_emitcode(";", "%d", __LINE__);
3879 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3880 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3882 if (strcmp(fReturn[offset],l)) {
3883 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3884 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3885 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3887 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3891 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3901 if (strcmp(fReturn[pushed],"a"))
3902 pic16_emitcode("pop",fReturn[pushed]);
3904 pic16_emitcode("pop","acc");
3910 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3913 /* generate a jump to the return label
3914 * if the next is not the return statement */
3915 if (!(ic->next && ic->next->op == LABEL
3916 && IC_LABEL(ic->next) == returnLabel)) {
3918 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3919 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3923 /*-----------------------------------------------------------------*/
3924 /* genLabel - generates a label */
3925 /*-----------------------------------------------------------------*/
3926 static void genLabel (iCode *ic)
3930 /* special case never generate */
3931 if (IC_LABEL(ic) == entryLabel)
3934 pic16_emitpLabel(IC_LABEL(ic)->key);
3935 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3938 /*-----------------------------------------------------------------*/
3939 /* genGoto - generates a goto */
3940 /*-----------------------------------------------------------------*/
3942 static void genGoto (iCode *ic)
3945 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3946 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3950 /*-----------------------------------------------------------------*/
3951 /* genMultbits :- multiplication of bits */
3952 /*-----------------------------------------------------------------*/
3953 static void genMultbits (operand *left,
3959 if(!pic16_sameRegs(AOP(result),AOP(right)))
3960 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3962 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3963 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3964 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3969 /*-----------------------------------------------------------------*/
3970 /* genMultOneByte : 8 bit multiplication & division */
3971 /*-----------------------------------------------------------------*/
3972 static void genMultOneByte (operand *left,
3978 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3979 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3981 /* (if two literals, the value is computed before) */
3982 /* if one literal, literal on the right */
3983 if (AOP_TYPE(left) == AOP_LIT){
3989 /* size is already checked in genMult == 1 */
3990 // size = AOP_SIZE(result);
3992 if (AOP_TYPE(right) == AOP_LIT){
3993 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3994 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3995 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3996 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3998 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3999 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4000 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4001 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4004 pic16_genMult8X8_8 (left, right,result);
4007 /*-----------------------------------------------------------------*/
4008 /* genMultOneWord : 16 bit multiplication */
4009 /*-----------------------------------------------------------------*/
4010 static void genMultOneWord (operand *left,
4015 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4016 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4018 /* (if two literals, the value is computed before)
4019 * if one literal, literal on the right */
4020 if (AOP_TYPE(left) == AOP_LIT){
4026 /* size is checked already == 2 */
4027 // size = AOP_SIZE(result);
4029 if (AOP_TYPE(right) == AOP_LIT) {
4030 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4031 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4032 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4033 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4035 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4036 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4037 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4038 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4041 pic16_genMult16X16_16(left, right,result);
4044 /*-----------------------------------------------------------------*/
4045 /* genMultOneLong : 32 bit multiplication */
4046 /*-----------------------------------------------------------------*/
4047 static void genMultOneLong (operand *left,
4052 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4053 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4055 /* (if two literals, the value is computed before)
4056 * if one literal, literal on the right */
4057 if (AOP_TYPE(left) == AOP_LIT){
4063 /* size is checked already == 4 */
4064 // size = AOP_SIZE(result);
4066 if (AOP_TYPE(right) == AOP_LIT) {
4067 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4068 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4069 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4070 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4072 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4073 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4074 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4075 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4078 pic16_genMult32X32_32(left, right,result);
4083 /*-----------------------------------------------------------------*/
4084 /* genMult - generates code for multiplication */
4085 /*-----------------------------------------------------------------*/
4086 static void genMult (iCode *ic)
4088 operand *left = IC_LEFT(ic);
4089 operand *right = IC_RIGHT(ic);
4090 operand *result= IC_RESULT(ic);
4093 /* assign the amsops */
4094 pic16_aopOp (left,ic,FALSE);
4095 pic16_aopOp (right,ic,FALSE);
4096 pic16_aopOp (result,ic,TRUE);
4098 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4100 /* special cases first *
4102 if (AOP_TYPE(left) == AOP_CRY
4103 && AOP_TYPE(right)== AOP_CRY) {
4104 genMultbits(left,right,result);
4108 /* if both are of size == 1 */
4109 if(AOP_SIZE(left) == 1
4110 && AOP_SIZE(right) == 1) {
4111 genMultOneByte(left,right,result);
4115 /* if both are of size == 2 */
4116 if(AOP_SIZE(left) == 2
4117 && AOP_SIZE(right) == 2) {
4118 genMultOneWord(left, right, result);
4122 /* if both are of size == 4 */
4123 if(AOP_SIZE(left) == 4
4124 && AOP_SIZE(right) == 4) {
4125 genMultOneLong(left, right, result);
4129 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4132 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4133 /* should have been converted to function call */
4137 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4138 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4139 pic16_freeAsmop(result,NULL,ic,TRUE);
4142 /*-----------------------------------------------------------------*/
4143 /* genDivbits :- division of bits */
4144 /*-----------------------------------------------------------------*/
4145 static void genDivbits (operand *left,
4152 /* the result must be bit */
4153 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4154 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4158 pic16_emitcode("div","ab");
4159 pic16_emitcode("rrc","a");
4160 pic16_aopPut(AOP(result),"c",0);
4163 /*-----------------------------------------------------------------*/
4164 /* genDivOneByte : 8 bit division */
4165 /*-----------------------------------------------------------------*/
4166 static void genDivOneByte (operand *left,
4170 sym_link *opetype = operandType(result);
4175 /* result = divident / divisor
4176 * - divident may be a register or a literal,
4177 * - divisor may be a register or a literal,
4178 * so there are 3 cases (literal / literal is optimized
4179 * by the front-end) to handle.
4180 * In addition we must handle signed and unsigned, which
4181 * result in 6 final different cases -- VR */
4185 size = AOP_SIZE(result) - 1;
4187 /* signed or unsigned */
4188 if (SPEC_USIGN(opetype)) {
4189 pCodeOp *pct1, /* count */
4192 symbol *label1, *label2, *label3;;
4195 /* unsigned is easy */
4197 pct1 = pic16_popGetTempReg(1);
4198 pct2 = pic16_popGetTempReg(1);
4199 pct3 = pic16_popGetTempReg(1);
4201 label1 = newiTempLabel(NULL);
4202 label2 = newiTempLabel(NULL);
4203 label3 = newiTempLabel(NULL);
4205 /* the following algorithm is extracted from divuint.c */
4207 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4208 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4210 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4212 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4214 pic16_emitpLabel(label1->key);
4217 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4221 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4225 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4227 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4228 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4230 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4231 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4232 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4234 pic16_emitpLabel( label3->key );
4235 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4236 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4240 pic16_emitpLabel(label2->key);
4241 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4242 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4243 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4245 /* result is in wreg */
4246 if(AOP_TYPE(result) != AOP_ACC)
4247 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4249 pic16_popReleaseTempReg( pct3, 1);
4250 pic16_popReleaseTempReg( pct2, 1);
4251 pic16_popReleaseTempReg( pct1, 1);
4256 /* signed is a little bit more difficult */
4258 /* save the signs of the operands */
4259 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4261 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4262 pic16_emitcode("push","acc"); /* save it on the stack */
4264 /* now sign adjust for both left & right */
4265 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4267 lbl = newiTempLabel(NULL);
4268 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4269 pic16_emitcode("cpl","a");
4270 pic16_emitcode("inc","a");
4271 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4272 pic16_emitcode("mov","b,a");
4274 /* sign adjust left side */
4275 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4278 lbl = newiTempLabel(NULL);
4279 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4280 pic16_emitcode("cpl","a");
4281 pic16_emitcode("inc","a");
4282 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4284 /* now the division */
4285 pic16_emitcode("div","ab");
4286 /* we are interested in the lower order
4288 pic16_emitcode("mov","b,a");
4289 lbl = newiTempLabel(NULL);
4290 pic16_emitcode("pop","acc");
4291 /* if there was an over flow we don't
4292 adjust the sign of the result */
4293 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4294 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4296 pic16_emitcode("clr","a");
4297 pic16_emitcode("subb","a,b");
4298 pic16_emitcode("mov","b,a");
4299 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4301 /* now we are done */
4302 pic16_aopPut(AOP(result),"b",0);
4304 pic16_emitcode("mov","c,b.7");
4305 pic16_emitcode("subb","a,acc");
4308 pic16_aopPut(AOP(result),"a",offset++);
4312 /*-----------------------------------------------------------------*/
4313 /* genDiv - generates code for division */
4314 /*-----------------------------------------------------------------*/
4315 static void genDiv (iCode *ic)
4317 operand *left = IC_LEFT(ic);
4318 operand *right = IC_RIGHT(ic);
4319 operand *result= IC_RESULT(ic);
4322 /* Division is a very lengthy algorithm, so it is better
4323 * to call support routines than inlining algorithm.
4324 * Division functions written here just in case someone
4325 * wants to inline and not use the support libraries -- VR */
4329 /* assign the amsops */
4330 pic16_aopOp (left,ic,FALSE);
4331 pic16_aopOp (right,ic,FALSE);
4332 pic16_aopOp (result,ic,TRUE);
4334 /* special cases first */
4336 if (AOP_TYPE(left) == AOP_CRY &&
4337 AOP_TYPE(right)== AOP_CRY) {
4338 genDivbits(left,right,result);
4342 /* if both are of size == 1 */
4343 if (AOP_SIZE(left) == 1 &&
4344 AOP_SIZE(right) == 1 ) {
4345 genDivOneByte(left,right,result);
4349 /* should have been converted to function call */
4352 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4353 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4354 pic16_freeAsmop(result,NULL,ic,TRUE);
4357 /*-----------------------------------------------------------------*/
4358 /* genModbits :- modulus of bits */
4359 /*-----------------------------------------------------------------*/
4360 static void genModbits (operand *left,
4368 werror(W_POSSBUG2, __FILE__, __LINE__);
4369 /* the result must be bit */
4370 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4371 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4375 pic16_emitcode("div","ab");
4376 pic16_emitcode("mov","a,b");
4377 pic16_emitcode("rrc","a");
4378 pic16_aopPut(AOP(result),"c",0);
4381 /*-----------------------------------------------------------------*/
4382 /* genModOneByte : 8 bit modulus */
4383 /*-----------------------------------------------------------------*/
4384 static void genModOneByte (operand *left,
4388 sym_link *opetype = operandType(result);
4393 werror(W_POSSBUG2, __FILE__, __LINE__);
4395 /* signed or unsigned */
4396 if (SPEC_USIGN(opetype)) {
4397 /* unsigned is easy */
4398 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4399 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4401 pic16_emitcode("div","ab");
4402 pic16_aopPut(AOP(result),"b",0);
4406 /* signed is a little bit more difficult */
4408 /* save the signs of the operands */
4409 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4412 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4413 pic16_emitcode("push","acc"); /* save it on the stack */
4415 /* now sign adjust for both left & right */
4416 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4419 lbl = newiTempLabel(NULL);
4420 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4421 pic16_emitcode("cpl","a");
4422 pic16_emitcode("inc","a");
4423 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4424 pic16_emitcode("mov","b,a");
4426 /* sign adjust left side */
4427 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4430 lbl = newiTempLabel(NULL);
4431 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4432 pic16_emitcode("cpl","a");
4433 pic16_emitcode("inc","a");
4434 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4436 /* now the multiplication */
4437 pic16_emitcode("div","ab");
4438 /* we are interested in the lower order
4440 lbl = newiTempLabel(NULL);
4441 pic16_emitcode("pop","acc");
4442 /* if there was an over flow we don't
4443 adjust the sign of the result */
4444 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4445 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4447 pic16_emitcode("clr","a");
4448 pic16_emitcode("subb","a,b");
4449 pic16_emitcode("mov","b,a");
4450 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4452 /* now we are done */
4453 pic16_aopPut(AOP(result),"b",0);
4457 /*-----------------------------------------------------------------*/
4458 /* genMod - generates code for division */
4459 /*-----------------------------------------------------------------*/
4460 static void genMod (iCode *ic)
4462 operand *left = IC_LEFT(ic);
4463 operand *right = IC_RIGHT(ic);
4464 operand *result= IC_RESULT(ic);
4468 /* assign the amsops */
4469 pic16_aopOp (left,ic,FALSE);
4470 pic16_aopOp (right,ic,FALSE);
4471 pic16_aopOp (result,ic,TRUE);
4473 /* special cases first */
4475 if (AOP_TYPE(left) == AOP_CRY &&
4476 AOP_TYPE(right)== AOP_CRY) {
4477 genModbits(left,right,result);
4481 /* if both are of size == 1 */
4482 if (AOP_SIZE(left) == 1 &&
4483 AOP_SIZE(right) == 1 ) {
4484 genModOneByte(left,right,result);
4488 /* should have been converted to function call */
4492 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4493 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4494 pic16_freeAsmop(result,NULL,ic,TRUE);
4497 /*-----------------------------------------------------------------*/
4498 /* genIfxJump :- will create a jump depending on the ifx */
4499 /*-----------------------------------------------------------------*/
4501 note: May need to add parameter to indicate when a variable is in bit space.
4503 static void genIfxJump (iCode *ic, char *jval)
4507 /* if true label then we jump if condition
4509 if ( IC_TRUE(ic) ) {
4511 if(strcmp(jval,"a") == 0)
4513 else if (strcmp(jval,"c") == 0)
4516 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4517 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4520 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4521 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4525 /* false label is present */
4526 if(strcmp(jval,"a") == 0)
4528 else if (strcmp(jval,"c") == 0)
4531 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4532 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4535 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4536 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4541 /* mark the icode as generated */
4548 /*-----------------------------------------------------------------*/
4550 /*-----------------------------------------------------------------*/
4551 static void genSkip(iCode *ifx,int status_bit)
4553 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4557 if ( IC_TRUE(ifx) ) {
4558 switch(status_bit) {
4573 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4574 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4578 switch(status_bit) {
4592 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4593 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4600 /*-----------------------------------------------------------------*/
4602 /*-----------------------------------------------------------------*/
4603 static void genSkipc(resolvedIfx *rifx)
4605 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4615 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4616 rifx->generated = 1;
4619 /*-----------------------------------------------------------------*/
4621 /*-----------------------------------------------------------------*/
4622 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4624 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4629 if( (rifx->condition ^ invert_condition) & 1)
4634 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4635 rifx->generated = 1;
4639 /*-----------------------------------------------------------------*/
4641 /*-----------------------------------------------------------------*/
4642 static void genSkipz(iCode *ifx, int condition)
4653 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4655 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4658 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4660 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4665 /*-----------------------------------------------------------------*/
4667 /*-----------------------------------------------------------------*/
4668 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4674 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4676 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4679 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4680 rifx->generated = 1;
4684 /*-----------------------------------------------------------------*/
4685 /* genChkZeroes :- greater or less than comparison */
4686 /* For each byte in a literal that is zero, inclusive or the */
4687 /* the corresponding byte in the operand with W */
4688 /* returns true if any of the bytes are zero */
4689 /*-----------------------------------------------------------------*/
4690 static int genChkZeroes(operand *op, int lit, int size)
4697 i = (lit >> (size*8)) & 0xff;
4701 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4703 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4712 /*-----------------------------------------------------------------*/
4713 /* genCmp :- greater or less than comparison */
4714 /*-----------------------------------------------------------------*/
4718 static void genCmp (operand *left,operand *right,
4719 operand *result, iCode *ifx, int sign)
4721 int size; //, offset = 0 ;
4722 unsigned long lit = 0L,i = 0;
4723 resolvedIfx rFalseIfx;
4724 // resolvedIfx rTrueIfx;
4726 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4729 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4730 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4736 resolveIfx(&rFalseIfx,ifx);
4737 truelbl = newiTempLabel(NULL);
4738 size = max(AOP_SIZE(left),AOP_SIZE(right));
4740 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4744 /* if literal is on the right then swap with left */
4745 if ((AOP_TYPE(right) == AOP_LIT)) {
4746 operand *tmp = right ;
4747 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4748 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4751 lit = (lit - 1) & mask;
4754 rFalseIfx.condition ^= 1;
4757 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4758 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4762 //if(IC_TRUE(ifx) == NULL)
4763 /* if left & right are bit variables */
4764 if (AOP_TYPE(left) == AOP_CRY &&
4765 AOP_TYPE(right) == AOP_CRY ) {
4766 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4767 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4769 /* subtract right from left if at the
4770 end the carry flag is set then we know that
4771 left is greater than right */
4773 symbol *lbl = newiTempLabel(NULL);
4776 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4777 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4781 if(AOP_TYPE(right) == AOP_LIT) {
4783 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4785 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4792 genSkipCond(&rFalseIfx,left,size-1,7);
4794 /* no need to compare to 0...*/
4795 /* NOTE: this is a de-generate compare that most certainly
4796 * creates some dead code. */
4797 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4799 if(ifx) ifx->generated = 1;
4806 //i = (lit >> (size*8)) & 0xff;
4807 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4809 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4811 i = ((0-lit) & 0xff);
4814 /* lit is 0x7f, all signed chars are less than
4815 * this except for 0x7f itself */
4816 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4817 genSkipz2(&rFalseIfx,0);
4819 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4820 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4821 genSkipc(&rFalseIfx);
4826 genSkipz2(&rFalseIfx,1);
4828 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4829 genSkipc(&rFalseIfx);
4833 if(ifx) ifx->generated = 1;
4837 /* chars are out of the way. now do ints and longs */
4840 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4847 genSkipCond(&rFalseIfx,left,size,7);
4848 if(ifx) ifx->generated = 1;
4853 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4855 //rFalseIfx.condition ^= 1;
4856 //genSkipCond(&rFalseIfx,left,size,7);
4857 //rFalseIfx.condition ^= 1;
4859 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4860 if(rFalseIfx.condition)
4861 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4863 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4865 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4866 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4867 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4870 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4872 if(rFalseIfx.condition) {
4874 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4880 genSkipc(&rFalseIfx);
4881 pic16_emitpLabel(truelbl->key);
4882 if(ifx) ifx->generated = 1;
4889 if( (lit & 0xff) == 0) {
4890 /* lower byte is zero */
4891 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4892 i = ((lit >> 8) & 0xff) ^0x80;
4893 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4894 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4895 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4896 genSkipc(&rFalseIfx);
4899 if(ifx) ifx->generated = 1;
4904 /* Special cases for signed longs */
4905 if( (lit & 0xffffff) == 0) {
4906 /* lower byte is zero */
4907 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4908 i = ((lit >> 8*3) & 0xff) ^0x80;
4909 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4910 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4911 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4912 genSkipc(&rFalseIfx);
4915 if(ifx) ifx->generated = 1;
4923 if(lit & (0x80 << (size*8))) {
4924 /* lit is negative */
4925 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4927 //genSkipCond(&rFalseIfx,left,size,7);
4929 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4931 if(rFalseIfx.condition)
4932 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4934 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4938 /* lit is positive */
4939 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4940 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4941 if(rFalseIfx.condition)
4942 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4944 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4949 This works, but is only good for ints.
4950 It also requires a "known zero" register.
4951 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4952 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4953 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
4954 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4955 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4956 genSkipc(&rFalseIfx);
4958 pic16_emitpLabel(truelbl->key);
4959 if(ifx) ifx->generated = 1;
4963 /* There are no more special cases, so perform a general compare */
4965 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4966 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4970 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4972 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4974 //rFalseIfx.condition ^= 1;
4975 genSkipc(&rFalseIfx);
4977 pic16_emitpLabel(truelbl->key);
4979 if(ifx) ifx->generated = 1;
4986 /* sign is out of the way. So now do an unsigned compare */
4987 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4990 /* General case - compare to an unsigned literal on the right.*/
4992 i = (lit >> (size*8)) & 0xff;
4993 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4994 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4996 i = (lit >> (size*8)) & 0xff;
4999 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5001 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5003 /* this byte of the lit is zero,
5004 *if it's not the last then OR in the variable */
5006 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5011 pic16_emitpLabel(lbl->key);
5012 // pic16_emitpLabel(truelbl->key);
5013 //if(emitFinalCheck)
5014 genSkipc(&rFalseIfx);
5016 pic16_emitpLabel(truelbl->key);
5018 if(ifx) ifx->generated = 1;
5025 if(AOP_TYPE(left) == AOP_LIT) {
5026 //symbol *lbl = newiTempLabel(NULL);
5028 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5031 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5034 if((lit == 0) && (sign == 0)){
5037 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5039 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5041 genSkipz2(&rFalseIfx,0);
5042 if(ifx) ifx->generated = 1;
5049 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5050 /* degenerate compare can never be true */
5051 if(rFalseIfx.condition == 0)
5052 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5054 if(ifx) ifx->generated = 1;
5059 /* signed comparisons to a literal byte */
5061 int lp1 = (lit+1) & 0xff;
5063 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5066 rFalseIfx.condition ^= 1;
5067 genSkipCond(&rFalseIfx,right,0,7);
5070 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5071 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5072 genSkipz2(&rFalseIfx,1);
5075 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5076 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5077 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5078 rFalseIfx.condition ^= 1;
5079 genSkipc(&rFalseIfx);
5083 /* unsigned comparisons to a literal byte */
5085 switch(lit & 0xff ) {
5087 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5088 genSkipz2(&rFalseIfx,0);
5091 rFalseIfx.condition ^= 1;
5092 genSkipCond(&rFalseIfx,right,0,7);
5096 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5097 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5098 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5099 rFalseIfx.condition ^= 1;
5100 if (AOP_TYPE(result) == AOP_CRY)
5101 genSkipc(&rFalseIfx);
5103 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5104 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5110 if(ifx) ifx->generated = 1;
5111 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5117 /* Size is greater than 1 */
5125 /* this means lit = 0xffffffff, or -1 */
5128 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5129 rFalseIfx.condition ^= 1;
5130 genSkipCond(&rFalseIfx,right,size,7);
5131 if(ifx) ifx->generated = 1;
5133 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5142 if(rFalseIfx.condition) {
5143 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5144 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5147 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5149 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5153 if(rFalseIfx.condition) {
5154 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5155 pic16_emitpLabel(truelbl->key);
5157 rFalseIfx.condition ^= 1;
5158 genSkipCond(&rFalseIfx,right,s,7);
5161 if(ifx) ifx->generated = 1;
5163 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5169 if((size == 1) && (0 == (lp1&0xff))) {
5170 /* lower byte of signed word is zero */
5171 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5172 i = ((lp1 >> 8) & 0xff) ^0x80;
5173 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5174 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5175 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5176 rFalseIfx.condition ^= 1;
5177 genSkipc(&rFalseIfx);
5180 if(ifx) ifx->generated = 1;
5182 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5188 if(lit & (0x80 << (size*8))) {
5189 /* Lit is less than zero */
5190 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5191 //rFalseIfx.condition ^= 1;
5192 //genSkipCond(&rFalseIfx,left,size,7);
5193 //rFalseIfx.condition ^= 1;
5194 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5195 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5197 if(rFalseIfx.condition)
5198 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5200 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5204 /* Lit is greater than or equal to zero */
5205 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5206 //rFalseIfx.condition ^= 1;
5207 //genSkipCond(&rFalseIfx,right,size,7);
5208 //rFalseIfx.condition ^= 1;
5210 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5211 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5213 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5214 if(rFalseIfx.condition)
5215 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5217 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5221 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5222 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5226 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5228 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5230 rFalseIfx.condition ^= 1;
5231 //rFalseIfx.condition = 1;
5232 genSkipc(&rFalseIfx);
5234 pic16_emitpLabel(truelbl->key);
5236 if(ifx) ifx->generated = 1;
5239 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5246 /* compare word or long to an unsigned literal on the right.*/
5251 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5254 break; /* handled above */
5257 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5259 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5260 genSkipz2(&rFalseIfx,0);
5264 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5266 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5269 if(rFalseIfx.condition)
5270 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5272 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5275 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5276 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5278 rFalseIfx.condition ^= 1;
5279 genSkipc(&rFalseIfx);
5282 pic16_emitpLabel(truelbl->key);
5284 if(ifx) ifx->generated = 1;
5286 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5294 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5295 i = (lit >> (size*8)) & 0xff;
5297 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5298 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5301 i = (lit >> (size*8)) & 0xff;
5304 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5306 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5308 /* this byte of the lit is zero,
5309 * if it's not the last then OR in the variable */
5311 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5316 pic16_emitpLabel(lbl->key);
5318 rFalseIfx.condition ^= 1;
5320 genSkipc(&rFalseIfx);
5324 pic16_emitpLabel(truelbl->key);
5325 if(ifx) ifx->generated = 1;
5327 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5333 /* Compare two variables */
5335 DEBUGpic16_emitcode(";sign","%d",sign);
5339 /* Sigh. thus sucks... */
5343 pctemp = pic16_popGetTempReg(1);
5344 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5345 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5346 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5347 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5348 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5349 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5350 pic16_popReleaseTempReg(pctemp, 1);
5352 /* Signed char comparison */
5353 /* Special thanks to Nikolai Golovchenko for this snippet */
5354 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5355 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5356 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5357 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5358 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5359 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5361 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5362 genSkipc(&rFalseIfx);
5364 if(ifx) ifx->generated = 1;
5366 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5374 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5375 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5379 /* The rest of the bytes of a multi-byte compare */
5383 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5386 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5387 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5392 pic16_emitpLabel(lbl->key);
5394 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5395 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5396 (AOP_TYPE(result) == AOP_REG)) {
5397 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5398 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5400 genSkipc(&rFalseIfx);
5402 //genSkipc(&rFalseIfx);
5403 if(ifx) ifx->generated = 1;
5406 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5414 if ((AOP_TYPE(result) != AOP_CRY)
5415 && AOP_SIZE(result)) {
5416 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5418 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5420 pic16_outBitC(result);
5422 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5423 /* if the result is used in the next
5424 ifx conditional branch then generate
5425 code a little differently */
5427 genIfxJump (ifx,"c");
5429 pic16_outBitC(result);
5430 /* leave the result in acc */
5435 #else /* old version of genCmp() */ /* } else { */
5437 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5438 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5439 operand *result, int offset, int invert_op)
5443 /* check condition, > or < ?? */
5444 if(rIfx->condition != 0)invert_op ^= 1;
5446 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5448 if(!ifx)invert_op ^= 1;
5450 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5451 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5454 if(!invert_op)return POC_CPFSGT;
5455 else return POC_CPFSLT;
5458 static int compareAopfirstpass=1;
5460 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5461 operand *oper, int offset, operand *result,
5462 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5468 /* invert if there is a result to be loaded, in order to fit,
5469 * SETC/CLRC sequence */
5470 if(AOP_SIZE(result))invert_op ^= 1;
5472 // if(sign && !offset)invert_op ^= 1;
5474 // if(sign)invert_op ^= 1;
5476 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5478 if(AOP_SIZE(result) && compareAopfirstpass) {
5481 pic16_emitpcode(POC_SETF, pcop2);
5486 pic16_emitpcode(POC_CLRF, pcop2);
5492 compareAopfirstpass = 0;
5494 /* there is a bug when comparing operands with size > 1,
5495 * because higher bytes can be equal and test should be performed
5496 * to the next lower byte, current algorithm, considers operands
5497 * inequal in these cases! -- VR 20041107 */
5501 pic16_emitpcode(op, pcop);
5503 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5506 if((!sign || !offset) && AOP_SIZE(result)) {
5509 pic16_emitpcode(POC_CLRF, pcop2);
5514 pic16_emitpcode(POC_SETF, pcop2);
5519 /* don't emit final branch (offset == 0) */
5523 pic16_emitpcode(POC_RRCF, pcop2);
5525 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5528 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5529 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5530 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5532 truelbl = newiTempLabel( NULL );
5533 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5534 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5535 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5537 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5538 pic16_emitpLabel(truelbl->key);
5540 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5549 static void genCmp (operand *left, operand *right,
5550 operand *result, iCode *ifx, int sign)
5554 resolvedIfx rFalseIfx;
5555 symbol *falselbl, *tlbl;
5559 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5561 resolveIfx(&rFalseIfx, ifx);
5562 size = max(AOP_SIZE(left), AOP_SIZE(right));
5564 /* if left & right are bit variables */
5565 if(AOP_TYPE(left) == AOP_CRY
5566 && AOP_TYPE(right) == AOP_CRY ) {
5568 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5569 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5571 werror(W_POSSBUG2, __FILE__, __LINE__);
5575 /* if literal is on the right then swap with left */
5576 if((AOP_TYPE(right) == AOP_LIT)) {
5577 operand *tmp = right ;
5578 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5580 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5582 // lit = (lit - 1) & mask;
5585 rFalseIfx.condition ^= 1; /* reverse compare */
5587 if ((AOP_TYPE(left) == AOP_LIT)) {
5588 /* float compares are handled by support functions */
5589 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5592 /* actual comparing algorithm */
5593 // size = AOP_SIZE( right );
5595 falselbl = newiTempLabel( NULL );
5596 if(AOP_TYPE(left) == AOP_LIT) {
5597 /* compare to literal */
5598 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5601 pCodeOp *pct, *pct2;
5604 /* signed compare */
5605 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5607 pct = pic16_popCopyReg(&pic16_pc_prodl);
5608 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5609 tlbl = newiTempLabel( NULL );
5611 /* first compare signs:
5612 * a. if both are positive, compare just like unsigned
5613 * b. if both are negative, invert cmpop, compare just like unsigned
5614 * c. if different signs, determine the result directly */
5620 tlbl1 = newiTempLabel( NULL );
5621 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
5625 /* literal is zero or positive:
5626 * a. if carry is zero, too, continue compare,
5627 * b. if carry is set, then continue depending on cmpop ^ condition:
5628 * 1. '<' return false (literal < variable),
5629 * 2. '>' return true (literal > variable) */
5630 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
5631 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5634 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5635 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
5639 /* literal is negative:
5640 * a. if carry is set, too, continue compare,
5641 * b. if carry is zero, then continue depending on cmpop ^ condition:
5642 * 1. '<' return true (literal < variable),
5643 * 2. '>' return false (literal > variable) */
5644 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
5645 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5647 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5648 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5653 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
5655 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
5656 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
5661 pic16_emitpLabel( tlbl1->key );
5664 compareAopfirstpass=1;
5665 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5666 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5667 // pic16_emitpcode(POC_MOVWF, pct);
5669 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5670 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5671 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5672 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5676 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5677 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
5678 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
5679 // pic16_emitpcode(POC_MOVWF, pct);
5681 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
5682 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
5683 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
5684 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5685 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5689 if(ifx)ifx->generated = 1;
5691 if(AOP_SIZE(result)) {
5692 pic16_emitpLabel(tlbl->key);
5693 pic16_emitpLabel(falselbl->key);
5694 pic16_outBitOp( result, pct2 );
5696 pic16_emitpLabel(tlbl->key);
5701 /* unsigned compare */
5702 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5704 compareAopfirstpass=1;
5707 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
5708 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5712 if(ifx)ifx->generated = 1;
5715 if(AOP_SIZE(result)) {
5716 pic16_emitpLabel(falselbl->key);
5717 pic16_outBitC( result );
5722 /* compare registers */
5723 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
5727 pCodeOp *pct, *pct2;
5729 /* signed compare */
5730 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5732 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
5733 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
5734 tlbl = newiTempLabel( NULL );
5736 compareAopfirstpass=1;
5739 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
5740 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5741 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5742 pic16_emitpcode(POC_MOVWF, pct);
5744 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5745 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5746 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5748 /* WREG already holds left + 0x80 */
5749 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5752 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
5753 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5754 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5755 pic16_emitpcode(POC_MOVWF, pct);
5757 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5758 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5759 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
5761 /* WREG already holds left + 0x80 */
5762 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
5763 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
5766 if(ifx)ifx->generated = 1;
5768 if(AOP_SIZE(result)) {
5769 pic16_emitpLabel(tlbl->key);
5770 pic16_emitpLabel(falselbl->key);
5771 pic16_outBitOp( result, pct2 );
5773 pic16_emitpLabel(tlbl->key);
5777 /* unsigned compare */
5778 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
5780 compareAopfirstpass=1;
5783 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
5784 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
5788 if(ifx)ifx->generated = 1;
5789 if(AOP_SIZE(result)) {
5791 pic16_emitpLabel(falselbl->key);
5792 pic16_outBitC( result );
5799 #else /* } else { */
5801 /* new version of genCmp -- VR 20041012 */
5802 static void genCmp (operand *left,operand *right,
5803 operand *result, iCode *ifx, int sign)
5805 int size; //, offset = 0 ;
5806 unsigned long lit = 0L,i = 0;
5807 resolvedIfx rFalseIfx;
5808 int willCheckCarry=0;
5809 // resolvedIfx rTrueIfx;
5815 * subtract right from left if at the end the carry flag is set then we
5816 * know that left is greater than right */
5818 resolveIfx(&rFalseIfx,ifx);
5819 truelbl = newiTempLabel(NULL);
5820 size = max(AOP_SIZE(left),AOP_SIZE(right));
5822 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5824 /* POC_CPFSGT compare f, wreg, skip if f greater than wreg
5825 * POC_CPFSLT compare f, wreg, skip if f less then wreg */
5828 /* if literal is on the right then swap with left */
5829 if ((AOP_TYPE(right) == AOP_LIT)) {
5830 operand *tmp = right ;
5831 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5833 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5835 // lit = (lit - 1) & mask;
5838 rFalseIfx.condition ^= 1; /* reverse compare */
5840 if ((AOP_TYPE(left) == AOP_LIT)) {
5841 /* float compares are handled by support functions */
5842 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5846 //if(IC_TRUE(ifx) == NULL)
5847 /* if left & right are bit variables */
5848 if (AOP_TYPE(left) == AOP_CRY &&
5849 AOP_TYPE(right) == AOP_CRY ) {
5851 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5852 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5855 symbol *lbl = newiTempLabel(NULL);
5857 if(AOP_TYPE(left) == AOP_LIT) {
5858 DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign);
5860 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5862 else willCheckCarry = 0;
5865 if((lit == 0) && (sign == 0)) {
5866 /* unsigned compare to 0 */
5867 DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign);
5870 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5872 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5874 genSkipz2(&rFalseIfx,0);
5875 if(ifx)ifx->generated = 1;
5882 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5883 /* degenerate compare can never be true */
5884 if(rFalseIfx.condition == 0)
5885 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5887 if(ifx) ifx->generated = 1;
5892 /* signed comparisons to a literal byte */
5893 DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
5895 int lp1 = (lit+1) & 0xff;
5897 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1);
5900 rFalseIfx.condition ^= 1;
5901 genSkipCond(&rFalseIfx,right,0,7);
5904 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5905 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5906 genSkipz2(&rFalseIfx,1);
5909 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit ));
5911 if(rFalseIfx.condition)
5912 pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0));
5914 pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0));
5916 if(willCheckCarry) {
5917 if(!rFalseIfx.condition) { emitCLRC; emitSETC; }
5918 else { emitSETC; emitCLRC; }
5921 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5924 /* pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5925 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5926 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5927 rFalseIfx.condition ^= 1;
5928 genSkipc(&rFalseIfx);
5933 /* unsigned comparisons to a literal byte */
5934 DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign);
5936 switch(lit & 0xff ) {
5939 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5940 genSkipz2(&rFalseIfx,0);
5943 rFalseIfx.condition ^= 1;
5944 genSkipCond(&rFalseIfx,right,0,7);
5947 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5948 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5949 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5950 rFalseIfx.condition ^= 1;
5951 if (AOP_TYPE(result) == AOP_CRY)
5952 genSkipc(&rFalseIfx);
5954 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5955 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5961 if(ifx) ifx->generated = 1;
5962 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5968 /* Size is greater than 1 */
5976 /* this means lit = 0xffffffff, or -1 */
5979 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5980 rFalseIfx.condition ^= 1;
5981 genSkipCond(&rFalseIfx,right,size,7);
5982 if(ifx) ifx->generated = 1;
5989 if(rFalseIfx.condition) {
5990 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5991 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5994 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5996 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6000 if(rFalseIfx.condition) {
6001 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6002 pic16_emitpLabel(truelbl->key);
6004 rFalseIfx.condition ^= 1;
6005 genSkipCond(&rFalseIfx,right,s,7);
6008 if(ifx) ifx->generated = 1;
6012 if((size == 1) && (0 == (lp1&0xff))) {
6013 /* lower byte of signed word is zero */
6014 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
6015 i = ((lp1 >> 8) & 0xff) ^0x80;
6016 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6017 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
6018 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
6019 rFalseIfx.condition ^= 1;
6020 genSkipc(&rFalseIfx);
6023 if(ifx) ifx->generated = 1;
6027 if(lit & (0x80 << (size*8))) {
6028 /* Lit is less than zero */
6029 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
6030 //rFalseIfx.condition ^= 1;
6031 //genSkipCond(&rFalseIfx,left,size,7);
6032 //rFalseIfx.condition ^= 1;
6033 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6034 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6036 if(rFalseIfx.condition)
6037 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6039 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6043 /* Lit is greater than or equal to zero */
6044 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
6045 //rFalseIfx.condition ^= 1;
6046 //genSkipCond(&rFalseIfx,right,size,7);
6047 //rFalseIfx.condition ^= 1;
6049 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
6050 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6052 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
6053 if(rFalseIfx.condition)
6054 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6056 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6061 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6062 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6066 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
6068 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6070 rFalseIfx.condition ^= 1;
6071 //rFalseIfx.condition = 1;
6072 genSkipc(&rFalseIfx);
6074 pic16_emitpLabel(truelbl->key);
6076 if(ifx) ifx->generated = 1;
6081 /* compare word or long to an unsigned literal on the right.*/
6086 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
6089 break; /* handled above */
6092 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6094 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6095 genSkipz2(&rFalseIfx,0);
6099 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6101 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6104 if(rFalseIfx.condition)
6105 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
6107 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
6110 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6111 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6113 rFalseIfx.condition ^= 1;
6114 genSkipc(&rFalseIfx);
6117 pic16_emitpLabel(truelbl->key);
6119 if(ifx) ifx->generated = 1;
6125 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6126 i = (lit >> (size*8)) & 0xff;
6128 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6129 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6132 i = (lit >> (size*8)) & 0xff;
6135 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6137 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6139 /* this byte of the lit is zero,
6140 * if it's not the last then OR in the variable */
6142 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6147 pic16_emitpLabel(lbl->key);
6149 rFalseIfx.condition ^= 1;
6151 genSkipc(&rFalseIfx);
6155 pic16_emitpLabel(truelbl->key);
6156 if(ifx) ifx->generated = 1;
6160 /* Compare two variables */
6162 DEBUGpic16_emitcode(";sign","%d",sign);
6166 /* Sigh. thus sucks... */
6170 pctemp = pic16_popGetTempReg(1);
6171 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6172 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
6173 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6174 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6175 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6176 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6177 pic16_popReleaseTempReg(pctemp, 1);
6179 /* Signed char comparison */
6180 /* Special thanks to Nikolai Golovchenko for this snippet */
6181 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6182 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6183 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
6184 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6185 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6186 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6188 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6189 genSkipc(&rFalseIfx);
6191 if(ifx) ifx->generated = 1;
6197 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6198 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6202 /* The rest of the bytes of a multi-byte compare */
6206 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
6209 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6210 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6215 pic16_emitpLabel(lbl->key);
6217 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6218 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6219 (AOP_TYPE(result) == AOP_REG)) {
6220 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6221 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6223 genSkipc(&rFalseIfx);
6225 //genSkipc(&rFalseIfx);
6226 if(ifx) ifx->generated = 1;
6233 if ((AOP_TYPE(result) != AOP_CRY)
6234 && AOP_SIZE(result)) {
6235 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6237 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6239 pic16_outBitC(result);
6241 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6242 /* if the result is used in the next
6243 ifx conditional branch then generate
6244 code a little differently */
6246 genIfxJump (ifx,"c");
6248 pic16_outBitC(result);
6249 /* leave the result in acc */
6260 /*-----------------------------------------------------------------*/
6261 /* genCmpGt :- greater than comparison */
6262 /*-----------------------------------------------------------------*/
6263 static void genCmpGt (iCode *ic, iCode *ifx)
6265 operand *left, *right, *result;
6266 sym_link *letype , *retype;
6272 right= IC_RIGHT(ic);
6273 result = IC_RESULT(ic);
6275 letype = getSpec(operandType(left));
6276 retype =getSpec(operandType(right));
6277 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6278 /* assign the amsops */
6279 pic16_aopOp (left,ic,FALSE);
6280 pic16_aopOp (right,ic,FALSE);
6281 pic16_aopOp (result,ic,TRUE);
6283 genCmp(right, left, result, ifx, sign);
6285 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6286 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6287 pic16_freeAsmop(result,NULL,ic,TRUE);
6290 /*-----------------------------------------------------------------*/
6291 /* genCmpLt - less than comparisons */
6292 /*-----------------------------------------------------------------*/
6293 static void genCmpLt (iCode *ic, iCode *ifx)
6295 operand *left, *right, *result;
6296 sym_link *letype , *retype;
6302 right= IC_RIGHT(ic);
6303 result = IC_RESULT(ic);
6305 letype = getSpec(operandType(left));
6306 retype =getSpec(operandType(right));
6307 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6309 /* assign the amsops */
6310 pic16_aopOp (left,ic,FALSE);
6311 pic16_aopOp (right,ic,FALSE);
6312 pic16_aopOp (result,ic,TRUE);
6314 genCmp(left, right, result, ifx, sign);
6316 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6317 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6318 pic16_freeAsmop(result,NULL,ic,TRUE);
6323 // FIXME reenable literal optimisation when the pic16 port is stable
6325 /*-----------------------------------------------------------------*/
6326 /* genc16bit2lit - compare a 16 bit value to a literal */
6327 /*-----------------------------------------------------------------*/
6328 static void genc16bit2lit(operand *op, int lit, int offset)
6332 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6333 if( (lit&0xff) == 0)
6338 switch( BYTEofLONG(lit,i)) {
6340 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6343 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6346 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6349 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6350 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6355 switch( BYTEofLONG(lit,i)) {
6357 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6361 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6365 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6368 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6370 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6379 /*-----------------------------------------------------------------*/
6380 /* gencjneshort - compare and jump if not equal */
6381 /*-----------------------------------------------------------------*/
6382 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6384 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6386 int res_offset = 0; /* the result may be a different size then left or right */
6387 int res_size = AOP_SIZE(result);
6389 symbol *lbl, *lbl_done;
6391 unsigned long lit = 0L;
6392 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6394 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6395 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6397 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6398 resolveIfx(&rIfx,ifx);
6399 lbl = newiTempLabel(NULL);
6400 lbl_done = newiTempLabel(NULL);
6403 /* if the left side is a literal or
6404 if the right is in a pointer register and left
6406 if ((AOP_TYPE(left) == AOP_LIT) ||
6407 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6412 if(AOP_TYPE(right) == AOP_LIT)
6413 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6415 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6416 preserve_result = 1;
6418 if(result && !preserve_result)
6421 for(i = 0; i < AOP_SIZE(result); i++)
6422 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6426 /* if the right side is a literal then anything goes */
6427 if (AOP_TYPE(right) == AOP_LIT &&
6428 AOP_TYPE(left) != AOP_DIR ) {
6431 genc16bit2lit(left, lit, 0);
6433 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6436 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6439 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6440 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6442 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6446 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6448 if(res_offset < res_size-1)
6456 /* if the right side is in a register or in direct space or
6457 if the left is a pointer register & right is not */
6458 else if (AOP_TYPE(right) == AOP_REG ||
6459 AOP_TYPE(right) == AOP_DIR ||
6460 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6461 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6462 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6463 int lbl_key = lbl->key;
6466 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6467 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6469 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6470 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6471 __FUNCTION__,__LINE__);
6475 /* switch(size) { */
6477 /* genc16bit2lit(left, lit, 0); */
6479 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6484 if((AOP_TYPE(left) == AOP_DIR) &&
6485 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6487 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6488 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6490 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6492 switch (lit & 0xff) {
6494 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6497 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6498 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6499 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6503 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6504 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6505 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6506 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6510 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6511 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6516 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6519 if(AOP_TYPE(result) == AOP_CRY) {
6520 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6525 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6527 /* fix me. probably need to check result size too */
6528 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6533 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6534 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6541 if(res_offset < res_size-1)
6546 } else if(AOP_TYPE(right) == AOP_REG &&
6547 AOP_TYPE(left) != AOP_DIR){
6550 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6551 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6552 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6557 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6559 if(res_offset < res_size-1)
6564 /* right is a pointer reg need both a & b */
6566 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6568 pic16_emitcode("mov","b,%s",l);
6569 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6570 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6575 if(result && preserve_result)
6578 for(i = 0; i < AOP_SIZE(result); i++)
6579 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6582 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6584 if(result && preserve_result)
6585 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6588 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6590 pic16_emitpLabel(lbl->key);
6592 if(result && preserve_result)
6595 for(i = 0; i < AOP_SIZE(result); i++)
6596 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6598 pic16_emitpLabel(lbl_done->key);
6601 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6609 /*-----------------------------------------------------------------*/
6610 /* gencjne - compare and jump if not equal */
6611 /*-----------------------------------------------------------------*/
6612 static void gencjne(operand *left, operand *right, iCode *ifx)
6614 symbol *tlbl = newiTempLabel(NULL);
6616 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6617 gencjneshort(left, right, lbl);
6619 pic16_emitcode("mov","a,%s",one);
6620 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6621 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6622 pic16_emitcode("clr","a");
6623 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6625 pic16_emitpLabel(lbl->key);
6626 pic16_emitpLabel(tlbl->key);
6632 /*-----------------------------------------------------------------*/
6633 /* is_LitOp - check if operand has to be treated as literal */
6634 /*-----------------------------------------------------------------*/
6635 static bool is_LitOp(operand *op)
6637 return ((AOP_TYPE(op) == AOP_LIT)
6638 || ( (AOP_TYPE(op) == AOP_PCODE)
6639 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6640 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6643 /*-----------------------------------------------------------------*/
6644 /* is_LitAOp - check if operand has to be treated as literal */
6645 /*-----------------------------------------------------------------*/
6646 static bool is_LitAOp(asmop *aop)
6648 return ((aop->type == AOP_LIT)
6649 || ( (aop->type == AOP_PCODE)
6650 && ( (aop->aopu.pcop->type == PO_LITERAL)
6651 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6656 /*-----------------------------------------------------------------*/
6657 /* genCmpEq - generates code for equal to */
6658 /*-----------------------------------------------------------------*/
6659 static void genCmpEq (iCode *ic, iCode *ifx)
6661 operand *left, *right, *result;
6662 symbol *falselbl = newiTempLabel(NULL);
6663 symbol *donelbl = newiTempLabel(NULL);
6665 int preserve_result = 0;
6666 int generate_result = 0;
6671 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6672 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6673 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6675 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6677 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6679 werror(W_POSSBUG2, __FILE__, __LINE__);
6680 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6681 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6685 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6687 operand *tmp = right ;
6692 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6693 preserve_result = 1;
6695 if(result && AOP_SIZE(result))
6696 generate_result = 1;
6698 if(generate_result && !preserve_result)
6700 for(i = 0; i < AOP_SIZE(result); i++)
6701 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6704 for(i=0; i < AOP_SIZE(left); i++)
6706 if(AOP_TYPE(left) != AOP_ACC)
6709 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6711 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6714 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6716 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6718 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6723 if(generate_result && preserve_result)
6725 for(i = 0; i < AOP_SIZE(result); i++)
6726 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6730 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6732 if(generate_result && preserve_result)
6733 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6735 if(ifx && IC_TRUE(ifx))
6736 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6738 if(ifx && IC_FALSE(ifx))
6739 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6741 pic16_emitpLabel(falselbl->key);
6745 if(ifx && IC_FALSE(ifx))
6746 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6748 if(generate_result && preserve_result)
6750 for(i = 0; i < AOP_SIZE(result); i++)
6751 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6754 pic16_emitpLabel(donelbl->key);
6760 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6761 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6762 pic16_freeAsmop(result,NULL,ic,TRUE);
6768 // old version kept for reference
6770 /*-----------------------------------------------------------------*/
6771 /* genCmpEq - generates code for equal to */
6772 /*-----------------------------------------------------------------*/
6773 static void genCmpEq (iCode *ic, iCode *ifx)
6775 operand *left, *right, *result;
6776 unsigned long lit = 0L;
6778 symbol *falselbl = newiTempLabel(NULL);
6781 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6784 DEBUGpic16_emitcode ("; ifx is non-null","");
6786 DEBUGpic16_emitcode ("; ifx is null","");
6788 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6789 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6790 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6792 size = max(AOP_SIZE(left),AOP_SIZE(right));
6794 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6796 /* if literal, literal on the right or
6797 if the right is in a pointer register and left
6799 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6800 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6801 operand *tmp = right ;
6807 if(ifx && !AOP_SIZE(result)){
6809 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6810 /* if they are both bit variables */
6811 if (AOP_TYPE(left) == AOP_CRY &&
6812 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6813 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6814 if(AOP_TYPE(right) == AOP_LIT){
6815 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6817 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6818 pic16_emitcode("cpl","c");
6819 } else if(lit == 1L) {
6820 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6822 pic16_emitcode("clr","c");
6824 /* AOP_TYPE(right) == AOP_CRY */
6826 symbol *lbl = newiTempLabel(NULL);
6827 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6828 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6829 pic16_emitcode("cpl","c");
6830 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6832 /* if true label then we jump if condition
6834 tlbl = newiTempLabel(NULL);
6835 if ( IC_TRUE(ifx) ) {
6836 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6837 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6839 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6840 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6842 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6845 /* left and right are both bit variables, result is carry */
6848 resolveIfx(&rIfx,ifx);
6850 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6851 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6852 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6853 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6858 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6860 /* They're not both bit variables. Is the right a literal? */
6861 if(AOP_TYPE(right) == AOP_LIT) {
6862 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6867 switch(lit & 0xff) {
6869 if ( IC_TRUE(ifx) ) {
6870 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6872 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6874 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6875 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6879 if ( IC_TRUE(ifx) ) {
6880 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6882 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6884 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6885 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6889 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6891 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6896 /* end of size == 1 */
6900 genc16bit2lit(left,lit,offset);
6903 /* end of size == 2 */
6908 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6909 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6910 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6911 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6914 /* search for patterns that can be optimized */
6916 genc16bit2lit(left,lit,0);
6920 emitSKPZ; // if hi word unequal
6922 emitSKPNZ; // if hi word equal
6924 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6925 genc16bit2lit(left,lit,2);
6928 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6929 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6933 pic16_emitpLabel(falselbl->key);
6942 } else if(AOP_TYPE(right) == AOP_CRY ) {
6943 /* we know the left is not a bit, but that the right is */
6944 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6945 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6946 pic16_popGet(AOP(right),offset));
6947 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6949 /* if the two are equal, then W will be 0 and the Z bit is set
6950 * we could test Z now, or go ahead and check the high order bytes if
6951 * the variable we're comparing is larger than a byte. */
6954 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6956 if ( IC_TRUE(ifx) ) {
6958 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6959 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6962 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6963 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6967 /* They're both variables that are larger than bits */
6970 tlbl = newiTempLabel(NULL);
6973 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6974 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6976 if ( IC_TRUE(ifx) ) {
6980 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6982 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6983 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6987 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6990 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6991 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6996 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6998 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6999 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7003 if(s>1 && IC_TRUE(ifx)) {
7004 pic16_emitpLabel(tlbl->key);
7005 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7009 /* mark the icode as generated */
7014 /* if they are both bit variables */
7015 if (AOP_TYPE(left) == AOP_CRY &&
7016 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7017 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7018 if(AOP_TYPE(right) == AOP_LIT){
7019 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7021 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7022 pic16_emitcode("cpl","c");
7023 } else if(lit == 1L) {
7024 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7026 pic16_emitcode("clr","c");
7028 /* AOP_TYPE(right) == AOP_CRY */
7030 symbol *lbl = newiTempLabel(NULL);
7031 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7032 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7033 pic16_emitcode("cpl","c");
7034 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7037 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7038 pic16_outBitC(result);
7042 genIfxJump (ifx,"c");
7045 /* if the result is used in an arithmetic operation
7046 then put the result in place */
7047 pic16_outBitC(result);
7050 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7051 gencjne(left,right,result,ifx);
7054 gencjne(left,right,newiTempLabel(NULL));
7056 if(IC_TRUE(ifx)->key)
7057 gencjne(left,right,IC_TRUE(ifx)->key);
7059 gencjne(left,right,IC_FALSE(ifx)->key);
7063 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7064 pic16_aopPut(AOP(result),"a",0);
7069 genIfxJump (ifx,"a");
7073 /* if the result is used in an arithmetic operation
7074 then put the result in place */
7076 if (AOP_TYPE(result) != AOP_CRY)
7077 pic16_outAcc(result);
7079 /* leave the result in acc */
7083 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7084 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7085 pic16_freeAsmop(result,NULL,ic,TRUE);
7089 /*-----------------------------------------------------------------*/
7090 /* ifxForOp - returns the icode containing the ifx for operand */
7091 /*-----------------------------------------------------------------*/
7092 static iCode *ifxForOp ( operand *op, iCode *ic )
7096 /* if true symbol then needs to be assigned */
7097 if (IS_TRUE_SYMOP(op))
7100 /* if this has register type condition and
7101 the next instruction is ifx with the same operand
7102 and live to of the operand is upto the ifx only then */
7104 && ic->next->op == IFX
7105 && IC_COND(ic->next)->key == op->key
7106 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7108 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7113 ic->next->op == IFX &&
7114 IC_COND(ic->next)->key == op->key) {
7115 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7119 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7121 ic->next->op == IFX)
7122 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7125 ic->next->op == IFX &&
7126 IC_COND(ic->next)->key == op->key) {
7127 DEBUGpic16_emitcode ("; "," key is okay");
7128 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7129 OP_SYMBOL(op)->liveTo,
7134 /* the code below is completely untested
7135 * it just allows ulong2fs.c compile -- VR */
7138 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7139 __FILE__, __FUNCTION__, __LINE__);
7141 /* if this has register type condition and
7142 the next instruction is ifx with the same operand
7143 and live to of the operand is upto the ifx only then */
7145 ic->next->op == IFX &&
7146 IC_COND(ic->next)->key == op->key &&
7147 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7151 ic->next->op == IFX &&
7152 IC_COND(ic->next)->key == op->key) {
7153 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7157 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7158 __FILE__, __FUNCTION__, __LINE__);
7160 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7165 /*-----------------------------------------------------------------*/
7166 /* genAndOp - for && operation */
7167 /*-----------------------------------------------------------------*/
7168 static void genAndOp (iCode *ic)
7170 operand *left,*right, *result;
7175 /* note here that && operations that are in an
7176 if statement are taken away by backPatchLabels
7177 only those used in arthmetic operations remain */
7178 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7179 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7180 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7182 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7184 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7185 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7186 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7188 /* if both are bit variables */
7189 /* if (AOP_TYPE(left) == AOP_CRY && */
7190 /* AOP_TYPE(right) == AOP_CRY ) { */
7191 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7192 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7193 /* pic16_outBitC(result); */
7195 /* tlbl = newiTempLabel(NULL); */
7196 /* pic16_toBoolean(left); */
7197 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7198 /* pic16_toBoolean(right); */
7199 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7200 /* pic16_outBitAcc(result); */
7203 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7204 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7205 pic16_freeAsmop(result,NULL,ic,TRUE);
7209 /*-----------------------------------------------------------------*/
7210 /* genOrOp - for || operation */
7211 /*-----------------------------------------------------------------*/
7214 modified this code, but it doesn't appear to ever get called
7217 static void genOrOp (iCode *ic)
7219 operand *left,*right, *result;
7224 /* note here that || operations that are in an
7225 if statement are taken away by backPatchLabels
7226 only those used in arthmetic operations remain */
7227 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7228 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7229 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
7231 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7233 /* if both are bit variables */
7234 if (AOP_TYPE(left) == AOP_CRY &&
7235 AOP_TYPE(right) == AOP_CRY ) {
7236 pic16_emitcode("clrc","");
7237 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7238 AOP(left)->aopu.aop_dir,
7239 AOP(left)->aopu.aop_dir);
7240 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7241 AOP(right)->aopu.aop_dir,
7242 AOP(right)->aopu.aop_dir);
7243 pic16_emitcode("setc","");
7246 tlbl = newiTempLabel(NULL);
7247 pic16_toBoolean(left);
7249 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7250 pic16_toBoolean(right);
7251 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7253 pic16_outBitAcc(result);
7256 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7257 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7258 pic16_freeAsmop(result,NULL,ic,TRUE);
7261 /*-----------------------------------------------------------------*/
7262 /* isLiteralBit - test if lit == 2^n */
7263 /*-----------------------------------------------------------------*/
7264 static int isLiteralBit(unsigned long lit)
7266 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7267 0x100L,0x200L,0x400L,0x800L,
7268 0x1000L,0x2000L,0x4000L,0x8000L,
7269 0x10000L,0x20000L,0x40000L,0x80000L,
7270 0x100000L,0x200000L,0x400000L,0x800000L,
7271 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7272 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7275 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7276 for(idx = 0; idx < 32; idx++)
7282 /*-----------------------------------------------------------------*/
7283 /* continueIfTrue - */
7284 /*-----------------------------------------------------------------*/
7285 static void continueIfTrue (iCode *ic)
7289 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7293 /*-----------------------------------------------------------------*/
7295 /*-----------------------------------------------------------------*/
7296 static void jumpIfTrue (iCode *ic)
7300 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7304 /*-----------------------------------------------------------------*/
7305 /* jmpTrueOrFalse - */
7306 /*-----------------------------------------------------------------*/
7307 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7309 // ugly but optimized by peephole
7312 symbol *nlbl = newiTempLabel(NULL);
7313 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7314 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7315 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7316 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7318 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7319 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7324 /*-----------------------------------------------------------------*/
7325 /* genAnd - code for and */
7326 /*-----------------------------------------------------------------*/
7327 static void genAnd (iCode *ic, iCode *ifx)
7329 operand *left, *right, *result;
7331 unsigned long lit = 0L;
7337 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7338 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7339 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7341 resolveIfx(&rIfx,ifx);
7343 /* if left is a literal & right is not then exchange them */
7344 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7345 AOP_NEEDSACC(left)) {
7346 operand *tmp = right ;
7351 /* if result = right then exchange them */
7352 if(pic16_sameRegs(AOP(result),AOP(right))){
7353 operand *tmp = right ;
7358 /* if right is bit then exchange them */
7359 if (AOP_TYPE(right) == AOP_CRY &&
7360 AOP_TYPE(left) != AOP_CRY){
7361 operand *tmp = right ;
7365 if(AOP_TYPE(right) == AOP_LIT)
7366 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7368 size = AOP_SIZE(result);
7370 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7373 // result = bit & yy;
7374 if (AOP_TYPE(left) == AOP_CRY){
7375 // c = bit & literal;
7376 if(AOP_TYPE(right) == AOP_LIT){
7378 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7381 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7384 if(size && (AOP_TYPE(result) == AOP_CRY)){
7385 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7388 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7392 pic16_emitcode("clr","c");
7395 if (AOP_TYPE(right) == AOP_CRY){
7397 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7398 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7401 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7403 pic16_emitcode("rrc","a");
7404 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7410 pic16_outBitC(result);
7412 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7413 genIfxJump(ifx, "c");
7417 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7418 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7419 if((AOP_TYPE(right) == AOP_LIT) &&
7420 (AOP_TYPE(result) == AOP_CRY) &&
7421 (AOP_TYPE(left) != AOP_CRY)){
7422 int posbit = isLiteralBit(lit);
7426 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7429 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7435 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7436 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7438 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7439 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7442 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7443 size = AOP_SIZE(left);
7446 int bp = posbit, ofs=0;
7453 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7454 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7458 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7459 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7461 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7468 symbol *tlbl = newiTempLabel(NULL);
7469 int sizel = AOP_SIZE(left);
7475 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7477 /* patch provided by Aaron Colwell */
7478 if((posbit = isLiteralBit(bytelit)) != 0) {
7479 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7480 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7481 (posbit-1),0, PO_GPR_REGISTER));
7483 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7484 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7486 if (bytelit == 0xff) {
7487 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7488 * a peephole could optimize it out -- VR */
7489 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7491 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7492 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7495 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7496 pic16_popGetLabel(tlbl->key));
7500 /* old code, left here for reference -- VR 09/2004 */
7501 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7503 if((posbit = isLiteralBit(bytelit)) != 0)
7504 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7506 if(bytelit != 0x0FFL)
7507 pic16_emitcode("anl","a,%s",
7508 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7509 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7515 // bit = left & literal
7518 pic16_emitpLabel(tlbl->key);
7520 // if(left & literal)
7523 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7526 pic16_emitpLabel(tlbl->key);
7531 pic16_outBitC(result);
7535 /* if left is same as result */
7536 if(pic16_sameRegs(AOP(result),AOP(left))){
7538 for(;size--; offset++,lit>>=8) {
7539 if(AOP_TYPE(right) == AOP_LIT){
7540 switch(lit & 0xff) {
7542 /* and'ing with 0 has clears the result */
7543 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7544 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7547 /* and'ing with 0xff is a nop when the result and left are the same */
7552 int p = pic16_my_powof2( (~lit) & 0xff );
7554 /* only one bit is set in the literal, so use a bcf instruction */
7555 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7556 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7559 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7560 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7561 if(know_W != (lit&0xff))
7562 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7564 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7569 if (AOP_TYPE(left) == AOP_ACC) {
7570 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7572 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7573 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7580 // left & result in different registers
7581 if(AOP_TYPE(result) == AOP_CRY){
7583 // if(size), result in bit
7584 // if(!size && ifx), conditional oper: if(left & right)
7585 symbol *tlbl = newiTempLabel(NULL);
7586 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7588 pic16_emitcode("setb","c");
7590 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7591 pic16_emitcode("anl","a,%s",
7592 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7593 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7598 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7599 pic16_outBitC(result);
7601 jmpTrueOrFalse(ifx, tlbl);
7603 for(;(size--);offset++) {
7605 // result = left & right
7606 if(AOP_TYPE(right) == AOP_LIT){
7607 int t = (lit >> (offset*8)) & 0x0FFL;
7610 pic16_emitcode("clrf","%s",
7611 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7612 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7615 pic16_emitcode("movf","%s,w",
7616 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7617 pic16_emitcode("movwf","%s",
7618 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7619 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7620 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7623 pic16_emitcode("movlw","0x%x",t);
7624 pic16_emitcode("andwf","%s,w",
7625 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7626 pic16_emitcode("movwf","%s",
7627 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7629 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7630 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7631 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7636 if (AOP_TYPE(left) == AOP_ACC) {
7637 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7638 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7640 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7641 pic16_emitcode("andwf","%s,w",
7642 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7643 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7644 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7646 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7647 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7653 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7654 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7655 pic16_freeAsmop(result,NULL,ic,TRUE);
7658 /*-----------------------------------------------------------------*/
7659 /* genOr - code for or */
7660 /*-----------------------------------------------------------------*/
7661 static void genOr (iCode *ic, iCode *ifx)
7663 operand *left, *right, *result;
7665 unsigned long lit = 0L;
7667 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7669 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7670 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7671 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7673 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7675 /* if left is a literal & right is not then exchange them */
7676 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7677 AOP_NEEDSACC(left)) {
7678 operand *tmp = right ;
7683 /* if result = right then exchange them */
7684 if(pic16_sameRegs(AOP(result),AOP(right))){
7685 operand *tmp = right ;
7690 /* if right is bit then exchange them */
7691 if (AOP_TYPE(right) == AOP_CRY &&
7692 AOP_TYPE(left) != AOP_CRY){
7693 operand *tmp = right ;
7698 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7700 if(AOP_TYPE(right) == AOP_LIT)
7701 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7703 size = AOP_SIZE(result);
7707 if (AOP_TYPE(left) == AOP_CRY){
7708 if(AOP_TYPE(right) == AOP_LIT){
7709 // c = bit & literal;
7711 // lit != 0 => result = 1
7712 if(AOP_TYPE(result) == AOP_CRY){
7714 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7715 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7716 // AOP(result)->aopu.aop_dir,
7717 // AOP(result)->aopu.aop_dir);
7719 continueIfTrue(ifx);
7723 // lit == 0 => result = left
7724 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7726 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7729 if (AOP_TYPE(right) == AOP_CRY){
7730 if(pic16_sameRegs(AOP(result),AOP(left))){
7732 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7733 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7734 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7736 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7737 AOP(result)->aopu.aop_dir,
7738 AOP(result)->aopu.aop_dir);
7739 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7740 AOP(right)->aopu.aop_dir,
7741 AOP(right)->aopu.aop_dir);
7742 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7743 AOP(result)->aopu.aop_dir,
7744 AOP(result)->aopu.aop_dir);
7746 if( AOP_TYPE(result) == AOP_ACC) {
7747 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7748 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7749 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7750 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7754 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7755 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7756 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7757 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7759 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7760 AOP(result)->aopu.aop_dir,
7761 AOP(result)->aopu.aop_dir);
7762 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7763 AOP(right)->aopu.aop_dir,
7764 AOP(right)->aopu.aop_dir);
7765 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7766 AOP(left)->aopu.aop_dir,
7767 AOP(left)->aopu.aop_dir);
7768 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7769 AOP(result)->aopu.aop_dir,
7770 AOP(result)->aopu.aop_dir);
7775 symbol *tlbl = newiTempLabel(NULL);
7776 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7779 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7780 if( AOP_TYPE(right) == AOP_ACC) {
7781 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7783 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7784 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7789 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7790 pic16_emitcode(";XXX setb","c");
7791 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7792 AOP(left)->aopu.aop_dir,tlbl->key+100);
7793 pic16_toBoolean(right);
7794 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7795 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7796 jmpTrueOrFalse(ifx, tlbl);
7800 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7807 pic16_outBitC(result);
7809 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7810 genIfxJump(ifx, "c");
7814 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7815 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7816 if((AOP_TYPE(right) == AOP_LIT) &&
7817 (AOP_TYPE(result) == AOP_CRY) &&
7818 (AOP_TYPE(left) != AOP_CRY)){
7820 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7823 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7825 continueIfTrue(ifx);
7828 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7829 // lit = 0, result = boolean(left)
7831 pic16_emitcode(";XXX setb","c");
7832 pic16_toBoolean(right);
7834 symbol *tlbl = newiTempLabel(NULL);
7835 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7837 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7839 genIfxJump (ifx,"a");
7843 pic16_outBitC(result);
7847 /* if left is same as result */
7848 if(pic16_sameRegs(AOP(result),AOP(left))){
7850 for(;size--; offset++,lit>>=8) {
7851 if(AOP_TYPE(right) == AOP_LIT){
7852 if((lit & 0xff) == 0)
7853 /* or'ing with 0 has no effect */
7856 int p = pic16_my_powof2(lit & 0xff);
7858 /* only one bit is set in the literal, so use a bsf instruction */
7859 pic16_emitpcode(POC_BSF,
7860 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7862 if(know_W != (lit & 0xff))
7863 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7864 know_W = lit & 0xff;
7865 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7870 if (AOP_TYPE(left) == AOP_ACC) {
7871 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7872 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7874 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7875 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7877 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7878 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7884 // left & result in different registers
7885 if(AOP_TYPE(result) == AOP_CRY){
7887 // if(size), result in bit
7888 // if(!size && ifx), conditional oper: if(left | right)
7889 symbol *tlbl = newiTempLabel(NULL);
7890 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7891 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7895 pic16_emitcode(";XXX setb","c");
7897 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7898 pic16_emitcode(";XXX orl","a,%s",
7899 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7900 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7905 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7906 pic16_outBitC(result);
7908 jmpTrueOrFalse(ifx, tlbl);
7909 } else for(;(size--);offset++){
7911 // result = left & right
7912 if(AOP_TYPE(right) == AOP_LIT){
7913 int t = (lit >> (offset*8)) & 0x0FFL;
7916 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7917 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7919 pic16_emitcode("movf","%s,w",
7920 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7921 pic16_emitcode("movwf","%s",
7922 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7925 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7926 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7927 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7929 pic16_emitcode("movlw","0x%x",t);
7930 pic16_emitcode("iorwf","%s,w",
7931 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7932 pic16_emitcode("movwf","%s",
7933 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7939 // faster than result <- left, anl result,right
7940 // and better if result is SFR
7941 if (AOP_TYPE(left) == AOP_ACC) {
7942 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7943 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7945 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7946 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7948 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7949 pic16_emitcode("iorwf","%s,w",
7950 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7952 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7953 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7958 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7959 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7960 pic16_freeAsmop(result,NULL,ic,TRUE);
7963 /*-----------------------------------------------------------------*/
7964 /* genXor - code for xclusive or */
7965 /*-----------------------------------------------------------------*/
7966 static void genXor (iCode *ic, iCode *ifx)
7968 operand *left, *right, *result;
7970 unsigned long lit = 0L;
7972 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7974 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7975 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7976 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7978 /* if left is a literal & right is not ||
7979 if left needs acc & right does not */
7980 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7981 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7982 operand *tmp = right ;
7987 /* if result = right then exchange them */
7988 if(pic16_sameRegs(AOP(result),AOP(right))){
7989 operand *tmp = right ;
7994 /* if right is bit then exchange them */
7995 if (AOP_TYPE(right) == AOP_CRY &&
7996 AOP_TYPE(left) != AOP_CRY){
7997 operand *tmp = right ;
8001 if(AOP_TYPE(right) == AOP_LIT)
8002 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8004 size = AOP_SIZE(result);
8008 if (AOP_TYPE(left) == AOP_CRY){
8009 if(AOP_TYPE(right) == AOP_LIT){
8010 // c = bit & literal;
8012 // lit>>1 != 0 => result = 1
8013 if(AOP_TYPE(result) == AOP_CRY){
8015 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8016 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8018 continueIfTrue(ifx);
8021 pic16_emitcode("setb","c");
8025 // lit == 0, result = left
8026 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8028 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8030 // lit == 1, result = not(left)
8031 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8032 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8033 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8034 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8037 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8038 pic16_emitcode("cpl","c");
8045 symbol *tlbl = newiTempLabel(NULL);
8046 if (AOP_TYPE(right) == AOP_CRY){
8048 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8051 int sizer = AOP_SIZE(right);
8053 // if val>>1 != 0, result = 1
8054 pic16_emitcode("setb","c");
8056 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8058 // test the msb of the lsb
8059 pic16_emitcode("anl","a,#0xfe");
8060 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8064 pic16_emitcode("rrc","a");
8066 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8067 pic16_emitcode("cpl","c");
8068 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8073 pic16_outBitC(result);
8075 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8076 genIfxJump(ifx, "c");
8080 if(pic16_sameRegs(AOP(result),AOP(left))){
8081 /* if left is same as result */
8082 for(;size--; offset++) {
8083 if(AOP_TYPE(right) == AOP_LIT){
8084 int t = (lit >> (offset*8)) & 0x0FFL;
8088 if (IS_AOP_PREG(left)) {
8089 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8090 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8091 pic16_aopPut(AOP(result),"a",offset);
8093 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8094 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8095 pic16_emitcode("xrl","%s,%s",
8096 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8097 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8100 if (AOP_TYPE(left) == AOP_ACC)
8101 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8103 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8104 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8106 if (IS_AOP_PREG(left)) {
8107 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8108 pic16_aopPut(AOP(result),"a",offset);
8110 pic16_emitcode("xrl","%s,a",
8111 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8117 // left & result in different registers
8118 if(AOP_TYPE(result) == AOP_CRY){
8120 // if(size), result in bit
8121 // if(!size && ifx), conditional oper: if(left ^ right)
8122 symbol *tlbl = newiTempLabel(NULL);
8123 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8125 pic16_emitcode("setb","c");
8127 if((AOP_TYPE(right) == AOP_LIT) &&
8128 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8129 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8131 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8132 pic16_emitcode("xrl","a,%s",
8133 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8135 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8140 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8141 pic16_outBitC(result);
8143 jmpTrueOrFalse(ifx, tlbl);
8144 } else for(;(size--);offset++){
8146 // result = left & right
8147 if(AOP_TYPE(right) == AOP_LIT){
8148 int t = (lit >> (offset*8)) & 0x0FFL;
8151 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8152 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8153 pic16_emitcode("movf","%s,w",
8154 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8155 pic16_emitcode("movwf","%s",
8156 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8159 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8160 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8161 pic16_emitcode("comf","%s,w",
8162 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8163 pic16_emitcode("movwf","%s",
8164 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8167 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8168 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8169 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8170 pic16_emitcode("movlw","0x%x",t);
8171 pic16_emitcode("xorwf","%s,w",
8172 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8173 pic16_emitcode("movwf","%s",
8174 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8180 // faster than result <- left, anl result,right
8181 // and better if result is SFR
8182 if (AOP_TYPE(left) == AOP_ACC) {
8183 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8184 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8186 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8187 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8188 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8189 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8191 if ( AOP_TYPE(result) != AOP_ACC){
8192 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8193 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8199 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8200 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8201 pic16_freeAsmop(result,NULL,ic,TRUE);
8204 /*-----------------------------------------------------------------*/
8205 /* genInline - write the inline code out */
8206 /*-----------------------------------------------------------------*/
8207 static void genInline (iCode *ic)
8209 char *buffer, *bp, *bp1;
8211 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8213 _G.inLine += (!options.asmpeep);
8215 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8216 strcpy(buffer,IC_INLINE(ic));
8218 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
8220 /* emit each line as a code */
8226 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8234 /* print label, use this special format with NULL directive
8235 * to denote that the argument should not be indented with tab */
8236 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8243 if ((bp1 != bp) && *bp1)
8244 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8249 _G.inLine -= (!options.asmpeep);
8252 /*-----------------------------------------------------------------*/
8253 /* genRRC - rotate right with carry */
8254 /*-----------------------------------------------------------------*/
8255 static void genRRC (iCode *ic)
8257 operand *left , *result ;
8258 int size, offset = 0, same;
8260 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8262 /* rotate right with carry */
8264 result=IC_RESULT(ic);
8265 pic16_aopOp (left,ic,FALSE);
8266 pic16_aopOp (result,ic,FALSE);
8268 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8270 same = pic16_sameRegs(AOP(result),AOP(left));
8272 size = AOP_SIZE(result);
8274 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8276 /* get the lsb and put it into the carry */
8277 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8284 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8286 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8287 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8293 pic16_freeAsmop(left,NULL,ic,TRUE);
8294 pic16_freeAsmop(result,NULL,ic,TRUE);
8297 /*-----------------------------------------------------------------*/
8298 /* genRLC - generate code for rotate left with carry */
8299 /*-----------------------------------------------------------------*/
8300 static void genRLC (iCode *ic)
8302 operand *left , *result ;
8303 int size, offset = 0;
8306 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8307 /* rotate right with carry */
8309 result=IC_RESULT(ic);
8310 pic16_aopOp (left,ic,FALSE);
8311 pic16_aopOp (result,ic,FALSE);
8313 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8315 same = pic16_sameRegs(AOP(result),AOP(left));
8317 /* move it to the result */
8318 size = AOP_SIZE(result);
8320 /* get the msb and put it into the carry */
8321 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8328 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8330 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8331 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8338 pic16_freeAsmop(left,NULL,ic,TRUE);
8339 pic16_freeAsmop(result,NULL,ic,TRUE);
8343 /* gpasm can get the highest order bit with HIGH/UPPER
8344 * so the following probably is not needed -- VR */
8346 /*-----------------------------------------------------------------*/
8347 /* genGetHbit - generates code get highest order bit */
8348 /*-----------------------------------------------------------------*/
8349 static void genGetHbit (iCode *ic)
8351 operand *left, *result;
8353 result=IC_RESULT(ic);
8354 pic16_aopOp (left,ic,FALSE);
8355 pic16_aopOp (result,ic,FALSE);
8357 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8358 /* get the highest order byte into a */
8359 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8360 if(AOP_TYPE(result) == AOP_CRY){
8361 pic16_emitcode("rlc","a");
8362 pic16_outBitC(result);
8365 pic16_emitcode("rl","a");
8366 pic16_emitcode("anl","a,#0x01");
8367 pic16_outAcc(result);
8371 pic16_freeAsmop(left,NULL,ic,TRUE);
8372 pic16_freeAsmop(result,NULL,ic,TRUE);
8376 /*-----------------------------------------------------------------*/
8377 /* AccRol - rotate left accumulator by known count */
8378 /*-----------------------------------------------------------------*/
8379 static void AccRol (int shCount)
8381 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8382 shCount &= 0x0007; // shCount : 0..7
8387 pic16_emitcode("rl","a");
8390 pic16_emitcode("rl","a");
8391 pic16_emitcode("rl","a");
8394 pic16_emitcode("swap","a");
8395 pic16_emitcode("rr","a");
8398 pic16_emitcode("swap","a");
8401 pic16_emitcode("swap","a");
8402 pic16_emitcode("rl","a");
8405 pic16_emitcode("rr","a");
8406 pic16_emitcode("rr","a");
8409 pic16_emitcode("rr","a");
8415 /*-----------------------------------------------------------------*/
8416 /* AccLsh - left shift accumulator by known count */
8417 /*-----------------------------------------------------------------*/
8418 static void AccLsh (int shCount)
8420 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8426 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8429 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8430 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8433 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8434 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8437 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8440 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8441 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8444 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8445 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8448 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8452 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8455 /*-----------------------------------------------------------------*/
8456 /* AccRsh - right shift accumulator by known count */
8457 /*-----------------------------------------------------------------*/
8458 static void AccRsh (int shCount, int andmask)
8460 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8465 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8468 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8469 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8472 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8473 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8476 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8479 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8480 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8483 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8484 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8487 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8492 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8494 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8498 /*-----------------------------------------------------------------*/
8499 /* AccSRsh - signed right shift accumulator by known count */
8500 /*-----------------------------------------------------------------*/
8501 static void AccSRsh (int shCount)
8504 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8507 pic16_emitcode("mov","c,acc.7");
8508 pic16_emitcode("rrc","a");
8509 } else if(shCount == 2){
8510 pic16_emitcode("mov","c,acc.7");
8511 pic16_emitcode("rrc","a");
8512 pic16_emitcode("mov","c,acc.7");
8513 pic16_emitcode("rrc","a");
8515 tlbl = newiTempLabel(NULL);
8516 /* rotate right accumulator */
8517 AccRol(8 - shCount);
8518 /* and kill the higher order bits */
8519 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8520 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8521 pic16_emitcode("orl","a,#0x%02x",
8522 (unsigned char)~SRMask[shCount]);
8523 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8529 /*-----------------------------------------------------------------*/
8530 /* shiftR1Left2Result - shift right one byte from left to result */
8531 /*-----------------------------------------------------------------*/
8532 static void shiftR1Left2ResultSigned (operand *left, int offl,
8533 operand *result, int offr,
8538 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8540 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8544 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8546 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8548 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8549 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),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));
8562 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8563 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8569 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8571 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8572 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8575 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8576 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8577 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8579 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8580 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8582 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8586 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8587 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8588 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8589 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8590 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8594 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8596 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8597 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8599 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8600 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8601 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8602 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8603 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8608 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8609 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8610 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8611 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8612 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8613 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8615 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8616 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8617 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8618 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8619 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8625 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8626 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8627 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8628 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8630 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8631 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8632 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
8640 /*-----------------------------------------------------------------*/
8641 /* shiftR1Left2Result - shift right one byte from left to result */
8642 /*-----------------------------------------------------------------*/
8643 static void shiftR1Left2Result (operand *left, int offl,
8644 operand *result, int offr,
8645 int shCount, int sign)
8649 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8651 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8653 /* Copy the msb into the carry if signed. */
8655 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8665 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8667 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8668 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8674 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8676 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8677 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8680 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8685 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8687 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8688 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8691 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8692 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8693 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8694 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8698 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8699 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8700 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8704 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8705 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8706 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8708 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8713 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8714 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8715 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8716 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8717 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8722 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8723 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8724 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8733 /*-----------------------------------------------------------------*/
8734 /* shiftL1Left2Result - shift left one byte from left to result */
8735 /*-----------------------------------------------------------------*/
8736 static void shiftL1Left2Result (operand *left, int offl,
8737 operand *result, int offr, int shCount)
8742 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8744 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8745 DEBUGpic16_emitcode ("; ***","same = %d",same);
8746 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8748 /* shift left accumulator */
8749 //AccLsh(shCount); // don't comment out just yet...
8750 // pic16_aopPut(AOP(result),"a",offr);
8754 /* Shift left 1 bit position */
8755 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8757 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8759 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8760 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8764 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8765 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8766 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8767 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8770 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8771 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8772 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8773 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8774 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8777 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8778 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8779 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8782 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8783 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8784 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8785 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8788 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8789 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8790 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8791 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8792 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8795 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8796 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8797 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8801 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8806 /*-----------------------------------------------------------------*/
8807 /* movLeft2Result - move byte from left to result */
8808 /*-----------------------------------------------------------------*/
8809 static void movLeft2Result (operand *left, int offl,
8810 operand *result, int offr)
8813 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8814 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8815 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8817 if (*l == '@' && (IS_AOP_PREG(result))) {
8818 pic16_emitcode("mov","a,%s",l);
8819 pic16_aopPut(AOP(result),"a",offr);
8821 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8822 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8827 /*-----------------------------------------------------------------*/
8828 /* shiftL2Left2Result - shift left two bytes from left to result */
8829 /*-----------------------------------------------------------------*/
8830 static void shiftL2Left2Result (operand *left, int offl,
8831 operand *result, int offr, int shCount)
8833 int same = pic16_sameRegs(AOP(result), AOP(left));
8836 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8838 if (same && (offl != offr)) { // shift bytes
8841 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8842 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8844 } else { // just treat as different later on
8857 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8858 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8859 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8863 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8864 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8870 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8871 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8872 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8873 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8874 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8875 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8876 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8878 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8879 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8883 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8884 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8885 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8886 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8887 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8888 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8889 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8890 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8891 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8892 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8895 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8896 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8897 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8898 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8899 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8909 /* note, use a mov/add for the shift since the mov has a
8910 chance of getting optimized out */
8911 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8912 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8913 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8914 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8915 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8919 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8920 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8926 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8927 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8928 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8929 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8930 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8931 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8932 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8933 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8937 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8938 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8942 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8943 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8944 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8945 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8947 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8948 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8949 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8950 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8951 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8952 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8953 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8954 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8957 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8958 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8959 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8960 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8961 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8966 /*-----------------------------------------------------------------*/
8967 /* shiftR2Left2Result - shift right two bytes from left to result */
8968 /*-----------------------------------------------------------------*/
8969 static void shiftR2Left2Result (operand *left, int offl,
8970 operand *result, int offr,
8971 int shCount, int sign)
8973 int same = pic16_sameRegs(AOP(result), AOP(left));
8975 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8977 if (same && (offl != offr)) { // shift right bytes
8980 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8981 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8983 } else { // just treat as different later on
8995 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9000 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9001 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9003 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9004 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9005 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9006 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9011 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9014 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9015 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9022 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9023 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9024 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9026 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9027 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9028 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9029 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9031 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9032 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9033 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9035 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9036 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9037 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9038 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9039 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9043 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9044 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9048 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9049 pic16_emitpcode(POC_BTFSC,
9050 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9051 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9059 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9060 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9062 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9063 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9064 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9065 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9067 pic16_emitpcode(POC_BTFSC,
9068 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9069 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9071 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9072 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9073 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9074 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9076 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9077 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9078 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9079 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9080 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9081 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9082 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9083 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9085 pic16_emitpcode(POC_BTFSC,
9086 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9087 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9089 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9090 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9097 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9098 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9099 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9100 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9103 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9105 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9110 /*-----------------------------------------------------------------*/
9111 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9112 /*-----------------------------------------------------------------*/
9113 static void shiftLLeftOrResult (operand *left, int offl,
9114 operand *result, int offr, int shCount)
9116 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9118 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9119 /* shift left accumulator */
9121 /* or with result */
9122 /* back to result */
9123 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9126 /*-----------------------------------------------------------------*/
9127 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9128 /*-----------------------------------------------------------------*/
9129 static void shiftRLeftOrResult (operand *left, int offl,
9130 operand *result, int offr, int shCount)
9132 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9134 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9135 /* shift right accumulator */
9137 /* or with result */
9138 /* back to result */
9139 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9142 /*-----------------------------------------------------------------*/
9143 /* genlshOne - left shift a one byte quantity by known count */
9144 /*-----------------------------------------------------------------*/
9145 static void genlshOne (operand *result, operand *left, int shCount)
9147 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9148 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9151 /*-----------------------------------------------------------------*/
9152 /* genlshTwo - left shift two bytes by known amount != 0 */
9153 /*-----------------------------------------------------------------*/
9154 static void genlshTwo (operand *result,operand *left, int shCount)
9158 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9159 size = pic16_getDataSize(result);
9161 /* if shCount >= 8 */
9167 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9169 movLeft2Result(left, LSB, result, MSB16);
9171 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9174 /* 1 <= shCount <= 7 */
9177 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9179 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9183 /*-----------------------------------------------------------------*/
9184 /* shiftLLong - shift left one long from left to result */
9185 /* offr = LSB or MSB16 */
9186 /*-----------------------------------------------------------------*/
9187 static void shiftLLong (operand *left, operand *result, int offr )
9189 int size = AOP_SIZE(result);
9190 int same = pic16_sameRegs(AOP(left),AOP(result));
9193 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9195 if (same && (offr == MSB16)) { //shift one byte
9196 for(i=size-1;i>=MSB16;i--) {
9197 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9198 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9201 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9204 if (size > LSB+offr ){
9206 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9208 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9209 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9213 if(size > MSB16+offr){
9215 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9217 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9218 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9222 if(size > MSB24+offr){
9224 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9226 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9227 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9231 if(size > MSB32+offr){
9233 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9235 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9236 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9240 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9244 /*-----------------------------------------------------------------*/
9245 /* genlshFour - shift four byte by a known amount != 0 */
9246 /*-----------------------------------------------------------------*/
9247 static void genlshFour (operand *result, operand *left, int shCount)
9251 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9252 size = AOP_SIZE(result);
9254 /* if shifting more that 3 bytes */
9255 if (shCount >= 24 ) {
9258 /* lowest order of left goes to the highest
9259 order of the destination */
9260 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9262 movLeft2Result(left, LSB, result, MSB32);
9264 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9265 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9266 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9271 /* more than two bytes */
9272 else if ( shCount >= 16 ) {
9273 /* lower order two bytes goes to higher order two bytes */
9275 /* if some more remaining */
9277 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9279 movLeft2Result(left, MSB16, result, MSB32);
9280 movLeft2Result(left, LSB, result, MSB24);
9282 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9283 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9287 /* if more than 1 byte */
9288 else if ( shCount >= 8 ) {
9289 /* lower order three bytes goes to higher order three bytes */
9293 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9295 movLeft2Result(left, LSB, result, MSB16);
9297 else{ /* size = 4 */
9299 movLeft2Result(left, MSB24, result, MSB32);
9300 movLeft2Result(left, MSB16, result, MSB24);
9301 movLeft2Result(left, LSB, result, MSB16);
9302 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9304 else if(shCount == 1)
9305 shiftLLong(left, result, MSB16);
9307 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9308 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9309 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9310 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9315 /* 1 <= shCount <= 7 */
9316 else if(shCount <= 3)
9318 shiftLLong(left, result, LSB);
9319 while(--shCount >= 1)
9320 shiftLLong(result, result, LSB);
9322 /* 3 <= shCount <= 7, optimize */
9324 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9325 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9326 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9330 /*-----------------------------------------------------------------*/
9331 /* genLeftShiftLiteral - left shifting by known count */
9332 /*-----------------------------------------------------------------*/
9333 void pic16_genLeftShiftLiteral (operand *left,
9338 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9342 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9343 pic16_freeAsmop(right,NULL,ic,TRUE);
9345 pic16_aopOp(left,ic,FALSE);
9346 pic16_aopOp(result,ic,FALSE);
9348 size = getSize(operandType(result));
9351 pic16_emitcode("; shift left ","result %d, left %d",size,
9355 /* I suppose that the left size >= result size */
9358 movLeft2Result(left, size, result, size);
9362 else if(shCount >= (size * 8))
9364 pic16_aopPut(AOP(result),zero,size);
9368 genlshOne (result,left,shCount);
9373 genlshTwo (result,left,shCount);
9377 genlshFour (result,left,shCount);
9381 pic16_freeAsmop(left,NULL,ic,TRUE);
9382 pic16_freeAsmop(result,NULL,ic,TRUE);
9385 /*-----------------------------------------------------------------*
9386 * genMultiAsm - repeat assembly instruction for size of register.
9387 * if endian == 1, then the high byte (i.e base address + size of
9388 * register) is used first else the low byte is used first;
9389 *-----------------------------------------------------------------*/
9390 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9395 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9408 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9413 /*-----------------------------------------------------------------*/
9414 /* genLeftShift - generates code for left shifting */
9415 /*-----------------------------------------------------------------*/
9416 static void genLeftShift (iCode *ic)
9418 operand *left,*right, *result;
9421 symbol *tlbl , *tlbl1;
9424 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9426 right = IC_RIGHT(ic);
9428 result = IC_RESULT(ic);
9430 pic16_aopOp(right,ic,FALSE);
9432 /* if the shift count is known then do it
9433 as efficiently as possible */
9434 if (AOP_TYPE(right) == AOP_LIT) {
9435 pic16_genLeftShiftLiteral (left,right,result,ic);
9439 /* shift count is unknown then we have to form
9440 * a loop. Get the loop count in WREG : Note: we take
9441 * only the lower order byte since shifting
9442 * more than 32 bits make no sense anyway, ( the
9443 * largest size of an object can be only 32 bits ) */
9445 pic16_aopOp(left,ic,FALSE);
9446 pic16_aopOp(result,ic,FALSE);
9448 /* now move the left to the result if they are not the
9449 * same, and if size > 1,
9450 * and if right is not same to result (!!!) -- VR */
9451 if (!pic16_sameRegs(AOP(left),AOP(result))
9452 && (AOP_SIZE(result) > 1)) {
9454 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9456 size = AOP_SIZE(result);
9461 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9462 if (*l == '@' && (IS_AOP_PREG(result))) {
9464 pic16_emitcode("mov","a,%s",l);
9465 pic16_aopPut(AOP(result),"a",offset);
9469 /* we don't know if left is a literal or a register, take care -- VR */
9470 mov2f(AOP(result), AOP(left), offset);
9476 size = AOP_SIZE(result);
9478 /* if it is only one byte then */
9480 if(optimized_for_speed) {
9481 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9482 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9483 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9484 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9485 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9486 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9487 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9488 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9489 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9490 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9491 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9492 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9495 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9497 tlbl = newiTempLabel(NULL);
9500 /* this is already done, why change it? */
9501 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9502 mov2f(AOP(result), AOP(left), 0);
9506 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9507 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9508 pic16_emitpLabel(tlbl->key);
9509 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9510 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9512 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9517 if (pic16_sameRegs(AOP(left),AOP(result))) {
9519 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9521 tlbl = newiTempLabel(NULL);
9522 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9523 genMultiAsm(POC_RRCF, result, size,1);
9524 pic16_emitpLabel(tlbl->key);
9525 genMultiAsm(POC_RLCF, result, size,0);
9526 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9528 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9532 //tlbl = newiTempLabel(NULL);
9534 //tlbl1 = newiTempLabel(NULL);
9536 //reAdjustPreg(AOP(result));
9538 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9539 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9540 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9542 //pic16_emitcode("add","a,acc");
9543 //pic16_aopPut(AOP(result),"a",offset++);
9545 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9547 // pic16_emitcode("rlc","a");
9548 // pic16_aopPut(AOP(result),"a",offset++);
9550 //reAdjustPreg(AOP(result));
9552 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9553 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9556 tlbl = newiTempLabel(NULL);
9557 tlbl1= newiTempLabel(NULL);
9559 size = AOP_SIZE(result);
9562 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9564 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9566 /* offset should be 0, 1 or 3 */
9568 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9570 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9572 pic16_emitpcode(POC_MOVWF, pctemp);
9575 pic16_emitpLabel(tlbl->key);
9578 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9580 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9582 pic16_emitpcode(POC_DECFSZ, pctemp);
9583 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9584 pic16_emitpLabel(tlbl1->key);
9586 pic16_popReleaseTempReg(pctemp,1);
9590 pic16_freeAsmop (right,NULL,ic,TRUE);
9591 pic16_freeAsmop(left,NULL,ic,TRUE);
9592 pic16_freeAsmop(result,NULL,ic,TRUE);
9598 #error old code (left here for reference)
9599 /*-----------------------------------------------------------------*/
9600 /* genLeftShift - generates code for left shifting */
9601 /*-----------------------------------------------------------------*/
9602 static void genLeftShift (iCode *ic)
9604 operand *left,*right, *result;
9607 symbol *tlbl , *tlbl1;
9610 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9612 right = IC_RIGHT(ic);
9614 result = IC_RESULT(ic);
9616 pic16_aopOp(right,ic,FALSE);
9618 /* if the shift count is known then do it
9619 as efficiently as possible */
9620 if (AOP_TYPE(right) == AOP_LIT) {
9621 pic16_genLeftShiftLiteral (left,right,result,ic);
9625 /* shift count is unknown then we have to form
9626 a loop get the loop count in B : Note: we take
9627 only the lower order byte since shifting
9628 more that 32 bits make no sense anyway, ( the
9629 largest size of an object can be only 32 bits ) */
9632 pic16_aopOp(left,ic,FALSE);
9633 pic16_aopOp(result,ic,FALSE);
9635 /* now move the left to the result if they are not the
9637 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9638 AOP_SIZE(result) > 1) {
9640 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9642 size = AOP_SIZE(result);
9645 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9646 if (*l == '@' && (IS_AOP_PREG(result))) {
9648 pic16_emitcode("mov","a,%s",l);
9649 pic16_aopPut(AOP(result),"a",offset);
9652 /* we don't know if left is a literal or a register, take care -- VR */
9653 mov2f(AOP(result), AOP(left), offset);
9659 size = AOP_SIZE(result);
9661 /* if it is only one byte then */
9663 if(optimized_for_speed) {
9664 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9665 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9666 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9667 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9668 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9669 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9670 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9671 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9672 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9673 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9674 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9675 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9678 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9680 tlbl = newiTempLabel(NULL);
9681 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9682 mov2f(AOP(result), AOP(left), 0);
9684 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9685 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9688 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9689 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9690 pic16_emitpLabel(tlbl->key);
9691 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9692 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9694 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9699 if (pic16_sameRegs(AOP(left),AOP(result))) {
9701 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9703 tlbl = newiTempLabel(NULL);
9704 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9705 genMultiAsm(POC_RRCF, result, size,1);
9706 pic16_emitpLabel(tlbl->key);
9707 genMultiAsm(POC_RLCF, result, size,0);
9708 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9710 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9714 //tlbl = newiTempLabel(NULL);
9716 //tlbl1 = newiTempLabel(NULL);
9718 //reAdjustPreg(AOP(result));
9720 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9721 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9722 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9724 //pic16_emitcode("add","a,acc");
9725 //pic16_aopPut(AOP(result),"a",offset++);
9727 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9729 // pic16_emitcode("rlc","a");
9730 // pic16_aopPut(AOP(result),"a",offset++);
9732 //reAdjustPreg(AOP(result));
9734 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9735 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9738 tlbl = newiTempLabel(NULL);
9739 tlbl1= newiTempLabel(NULL);
9741 size = AOP_SIZE(result);
9744 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9746 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9748 /* offset should be 0, 1 or 3 */
9750 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9752 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9754 pic16_emitpcode(POC_MOVWF, pctemp);
9757 pic16_emitpLabel(tlbl->key);
9760 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9762 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9764 pic16_emitpcode(POC_DECFSZ, pctemp);
9765 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9766 pic16_emitpLabel(tlbl1->key);
9768 pic16_popReleaseTempReg(pctemp,1);
9772 pic16_freeAsmop (right,NULL,ic,TRUE);
9773 pic16_freeAsmop(left,NULL,ic,TRUE);
9774 pic16_freeAsmop(result,NULL,ic,TRUE);
9778 /*-----------------------------------------------------------------*/
9779 /* genrshOne - right shift a one byte quantity by known count */
9780 /*-----------------------------------------------------------------*/
9781 static void genrshOne (operand *result, operand *left,
9782 int shCount, int sign)
9784 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9785 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9788 /*-----------------------------------------------------------------*/
9789 /* genrshTwo - right shift two bytes by known amount != 0 */
9790 /*-----------------------------------------------------------------*/
9791 static void genrshTwo (operand *result,operand *left,
9792 int shCount, int sign)
9794 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9795 /* if shCount >= 8 */
9799 shiftR1Left2Result(left, MSB16, result, LSB,
9802 movLeft2Result(left, MSB16, result, LSB);
9804 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9807 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9808 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
9812 /* 1 <= shCount <= 7 */
9814 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9817 /*-----------------------------------------------------------------*/
9818 /* shiftRLong - shift right one long from left to result */
9819 /* offl = LSB or MSB16 */
9820 /*-----------------------------------------------------------------*/
9821 static void shiftRLong (operand *left, int offl,
9822 operand *result, int sign)
9824 int size = AOP_SIZE(result);
9825 int same = pic16_sameRegs(AOP(left),AOP(result));
9827 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9829 if (same && (offl == MSB16)) { //shift one byte right
9830 for(i=MSB16;i<size;i++) {
9831 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9832 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9837 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9843 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9845 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9846 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9850 /* add sign of "a" */
9851 pic16_addSign(result, MSB32, sign);
9855 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9857 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9858 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9862 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9864 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9865 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9869 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9872 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9873 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9878 /*-----------------------------------------------------------------*/
9879 /* genrshFour - shift four byte by a known amount != 0 */
9880 /*-----------------------------------------------------------------*/
9881 static void genrshFour (operand *result, operand *left,
9882 int shCount, int sign)
9884 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9885 /* if shifting more that 3 bytes */
9886 if(shCount >= 24 ) {
9889 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9891 movLeft2Result(left, MSB32, result, LSB);
9893 pic16_addSign(result, MSB16, sign);
9895 else if(shCount >= 16){
9898 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9900 movLeft2Result(left, MSB24, result, LSB);
9901 movLeft2Result(left, MSB32, result, MSB16);
9903 pic16_addSign(result, MSB24, sign);
9905 else if(shCount >= 8){
9908 shiftRLong(left, MSB16, result, sign);
9909 else if(shCount == 0){
9910 movLeft2Result(left, MSB16, result, LSB);
9911 movLeft2Result(left, MSB24, result, MSB16);
9912 movLeft2Result(left, MSB32, result, MSB24);
9913 pic16_addSign(result, MSB32, sign);
9915 else{ //shcount >= 2
9916 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9917 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9918 /* the last shift is signed */
9919 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9920 pic16_addSign(result, MSB32, sign);
9923 else{ /* 1 <= shCount <= 7 */
9925 shiftRLong(left, LSB, result, sign);
9927 shiftRLong(result, LSB, result, sign);
9930 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9931 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9932 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9937 /*-----------------------------------------------------------------*/
9938 /* genRightShiftLiteral - right shifting by known count */
9939 /*-----------------------------------------------------------------*/
9940 static void genRightShiftLiteral (operand *left,
9946 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
9949 pic16_freeAsmop(right,NULL,ic,TRUE);
9951 pic16_aopOp(left,ic,FALSE);
9952 pic16_aopOp(result,ic,FALSE);
9954 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9957 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9961 lsize = pic16_getDataSize(left);
9962 res_size = pic16_getDataSize(result);
9963 /* test the LEFT size !!! */
9965 /* I suppose that the left size >= result size */
9968 movLeft2Result(left, lsize, result, res_size);
9971 else if(shCount >= (lsize * 8)){
9974 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9976 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9977 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
9982 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9983 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9984 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9986 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9991 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9998 genrshOne (result,left,shCount,sign);
10002 genrshTwo (result,left,shCount,sign);
10006 genrshFour (result,left,shCount,sign);
10014 pic16_freeAsmop(left,NULL,ic,TRUE);
10015 pic16_freeAsmop(result,NULL,ic,TRUE);
10018 /*-----------------------------------------------------------------*/
10019 /* genSignedRightShift - right shift of signed number */
10020 /*-----------------------------------------------------------------*/
10021 static void genSignedRightShift (iCode *ic)
10023 operand *right, *left, *result;
10026 symbol *tlbl, *tlbl1 ;
10029 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10031 /* we do it the hard way put the shift count in b
10032 and loop thru preserving the sign */
10033 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10035 right = IC_RIGHT(ic);
10036 left = IC_LEFT(ic);
10037 result = IC_RESULT(ic);
10039 pic16_aopOp(right,ic,FALSE);
10040 pic16_aopOp(left,ic,FALSE);
10041 pic16_aopOp(result,ic,FALSE);
10044 if ( AOP_TYPE(right) == AOP_LIT) {
10045 genRightShiftLiteral (left,right,result,ic,1);
10048 /* shift count is unknown then we have to form
10049 a loop get the loop count in B : Note: we take
10050 only the lower order byte since shifting
10051 more that 32 bits make no sense anyway, ( the
10052 largest size of an object can be only 32 bits ) */
10054 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10055 //pic16_emitcode("inc","b");
10056 //pic16_freeAsmop (right,NULL,ic,TRUE);
10057 //pic16_aopOp(left,ic,FALSE);
10058 //pic16_aopOp(result,ic,FALSE);
10060 /* now move the left to the result if they are not the
10062 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10063 AOP_SIZE(result) > 1) {
10065 size = AOP_SIZE(result);
10069 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10070 if (*l == '@' && IS_AOP_PREG(result)) {
10072 pic16_emitcode("mov","a,%s",l);
10073 pic16_aopPut(AOP(result),"a",offset);
10075 pic16_aopPut(AOP(result),l,offset);
10077 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10078 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10084 /* mov the highest order bit to OVR */
10085 tlbl = newiTempLabel(NULL);
10086 tlbl1= newiTempLabel(NULL);
10088 size = AOP_SIZE(result);
10091 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10093 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10095 /* offset should be 0, 1 or 3 */
10096 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10098 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10100 pic16_emitpcode(POC_MOVWF, pctemp);
10103 pic16_emitpLabel(tlbl->key);
10105 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10106 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10109 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10112 pic16_emitpcode(POC_DECFSZ, pctemp);
10113 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10114 pic16_emitpLabel(tlbl1->key);
10116 pic16_popReleaseTempReg(pctemp,1);
10118 size = AOP_SIZE(result);
10120 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10121 pic16_emitcode("rlc","a");
10122 pic16_emitcode("mov","ov,c");
10123 /* if it is only one byte then */
10125 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10127 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10128 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10129 pic16_emitcode("mov","c,ov");
10130 pic16_emitcode("rrc","a");
10131 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10132 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10133 pic16_aopPut(AOP(result),"a",0);
10137 reAdjustPreg(AOP(result));
10138 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10139 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10140 pic16_emitcode("mov","c,ov");
10142 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10144 pic16_emitcode("rrc","a");
10145 pic16_aopPut(AOP(result),"a",offset--);
10147 reAdjustPreg(AOP(result));
10148 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10149 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10154 pic16_freeAsmop(left,NULL,ic,TRUE);
10155 pic16_freeAsmop(result,NULL,ic,TRUE);
10156 pic16_freeAsmop(right,NULL,ic,TRUE);
10159 /*-----------------------------------------------------------------*/
10160 /* genRightShift - generate code for right shifting */
10161 /*-----------------------------------------------------------------*/
10162 static void genRightShift (iCode *ic)
10164 operand *right, *left, *result;
10168 symbol *tlbl, *tlbl1 ;
10170 /* if signed then we do it the hard way preserve the
10171 sign bit moving it inwards */
10172 letype = getSpec(operandType(IC_LEFT(ic)));
10173 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10175 if (!SPEC_USIGN(letype)) {
10176 genSignedRightShift (ic);
10180 /* signed & unsigned types are treated the same : i.e. the
10181 signed is NOT propagated inwards : quoting from the
10182 ANSI - standard : "for E1 >> E2, is equivalent to division
10183 by 2**E2 if unsigned or if it has a non-negative value,
10184 otherwise the result is implementation defined ", MY definition
10185 is that the sign does not get propagated */
10187 right = IC_RIGHT(ic);
10188 left = IC_LEFT(ic);
10189 result = IC_RESULT(ic);
10191 pic16_aopOp(right,ic,FALSE);
10193 /* if the shift count is known then do it
10194 as efficiently as possible */
10195 if (AOP_TYPE(right) == AOP_LIT) {
10196 genRightShiftLiteral (left,right,result,ic, 0);
10200 /* shift count is unknown then we have to form
10201 a loop get the loop count in B : Note: we take
10202 only the lower order byte since shifting
10203 more that 32 bits make no sense anyway, ( the
10204 largest size of an object can be only 32 bits ) */
10206 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10207 pic16_emitcode("inc","b");
10208 pic16_aopOp(left,ic,FALSE);
10209 pic16_aopOp(result,ic,FALSE);
10211 /* now move the left to the result if they are not the
10213 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10214 AOP_SIZE(result) > 1) {
10216 size = AOP_SIZE(result);
10219 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10220 if (*l == '@' && IS_AOP_PREG(result)) {
10222 pic16_emitcode("mov","a,%s",l);
10223 pic16_aopPut(AOP(result),"a",offset);
10225 pic16_aopPut(AOP(result),l,offset);
10230 tlbl = newiTempLabel(NULL);
10231 tlbl1= newiTempLabel(NULL);
10232 size = AOP_SIZE(result);
10235 /* if it is only one byte then */
10238 tlbl = newiTempLabel(NULL);
10239 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10240 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10241 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10244 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10245 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10246 pic16_emitpLabel(tlbl->key);
10247 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10248 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10250 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10255 reAdjustPreg(AOP(result));
10256 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10257 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10260 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10262 pic16_emitcode("rrc","a");
10263 pic16_aopPut(AOP(result),"a",offset--);
10265 reAdjustPreg(AOP(result));
10267 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10268 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10271 pic16_freeAsmop(left,NULL,ic,TRUE);
10272 pic16_freeAsmop (right,NULL,ic,TRUE);
10273 pic16_freeAsmop(result,NULL,ic,TRUE);
10277 void pic16_loadFSR0(operand *op)
10279 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10282 /*-----------------------------------------------------------------*/
10283 /* genUnpackBits - generates code for unpacking bits */
10284 /*-----------------------------------------------------------------*/
10285 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10289 sym_link *etype, *letype;
10290 int blen=0, bstr=0;
10294 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10295 etype = getSpec(operandType(result));
10296 letype = getSpec(operandType(left));
10298 // if(IS_BITFIELD(etype)) {
10299 blen = SPEC_BLEN(etype);
10300 bstr = SPEC_BSTR(etype);
10303 lbstr = SPEC_BSTR( letype );
10306 if((blen == 1) && (bstr < 8)) {
10307 /* it is a single bit, so use the appropriate bit instructions */
10308 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10310 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10312 if((ptype == POINTER) && (result)) {
10313 /* workaround to reduce the extra lfsr instruction */
10314 pic16_emitpcode(POC_BTFSC,
10315 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10317 pic16_emitpcode(POC_BTFSC,
10318 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10321 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10323 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10329 /* the following call to pic16_loadFSR0 is temporary until
10330 * optimization to handle single bit assignments is added
10331 * to the function. Until then use the old safe way! -- VR */
10332 pic16_loadFSR0( left );
10334 /* read the first byte */
10341 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10344 pic16_emitcode("clr","a");
10345 pic16_emitcode("movc","a","@a+dptr");
10350 /* if we have bitdisplacement then it fits */
10351 /* into this byte completely or if length is */
10352 /* less than a byte */
10353 if ((shCnt = SPEC_BSTR(etype)) ||
10354 (SPEC_BLEN(etype) <= 8)) {
10356 /* shift right acc */
10359 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10360 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10362 /* VR -- normally I would use the following, but since we use the hack,
10363 * to avoid the masking from AccRsh, why not mask it right now? */
10366 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10369 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10375 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10376 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10379 /* bit field did not fit in a byte */
10380 rlen = SPEC_BLEN(etype) - 8;
10381 pic16_aopPut(AOP(result),"a",offset++);
10388 pic16_emitcode("inc","%s",rname);
10389 pic16_emitcode("mov","a,@%s",rname);
10393 pic16_emitcode("inc","%s",rname);
10394 pic16_emitcode("movx","a,@%s",rname);
10398 pic16_emitcode("inc","dptr");
10399 pic16_emitcode("movx","a,@dptr");
10403 pic16_emitcode("clr","a");
10404 pic16_emitcode("inc","dptr");
10405 pic16_emitcode("movc","a","@a+dptr");
10409 pic16_emitcode("inc","dptr");
10410 pic16_emitcode("lcall","__gptrget");
10415 /* if we are done */
10419 pic16_aopPut(AOP(result),"a",offset++);
10424 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10425 pic16_aopPut(AOP(result),"a",offset);
10432 static void genDataPointerGet(operand *left,
10436 int size, offset = 0, leoffset=0 ;
10438 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10439 pic16_aopOp(result, ic, FALSE);
10441 size = AOP_SIZE(result);
10442 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10446 /* The following tests may save a redudant movff instruction when
10447 * accessing unions */
10449 /* if they are the same */
10450 if (operandsEqu (left, result)) {
10451 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10457 /* if they are the same registers */
10458 if (pic16_sameRegs(AOP(left),AOP(result))) {
10459 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10465 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10466 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10467 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10474 if ( AOP_TYPE(left) == AOP_PCODE) {
10475 fprintf(stderr,"genDataPointerGet %s, %d\n",
10476 AOP(left)->aopu.pcop->name,
10477 (AOP(left)->aopu.pcop->type == PO_DIR)?
10478 PCOR(AOP(left)->aopu.pcop)->instance:
10479 PCOI(AOP(left)->aopu.pcop)->offset);
10483 if(AOP(left)->aopu.pcop->type == PO_DIR)
10484 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10486 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10489 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10491 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
10492 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
10493 mov2w(AOP(left), offset); // patch 8
10494 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10496 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10497 pic16_popGet(AOP(left), offset), //patch 8
10498 pic16_popGet(AOP(result), offset)));
10506 pic16_freeAsmop(result,NULL,ic,TRUE);
10511 /*-----------------------------------------------------------------*/
10512 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10513 /*-----------------------------------------------------------------*/
10514 static void genNearPointerGet (operand *left,
10519 //regs *preg = NULL ;
10520 sym_link *rtype, *retype;
10521 sym_link *ltype = operandType(left);
10525 rtype = operandType(result);
10526 retype= getSpec(rtype);
10528 pic16_aopOp(left,ic,FALSE);
10530 // pic16_DumpOp("(left)",left);
10531 // pic16_DumpOp("(result)",result);
10533 /* if left is rematerialisable and
10534 * result is not bit variable type and
10535 * the left is pointer to data space i.e
10536 * lower 128 bytes of space */
10538 if (AOP_TYPE(left) == AOP_PCODE
10539 && !IS_BITFIELD(retype)
10540 && DCL_TYPE(ltype) == POINTER) {
10542 genDataPointerGet (left,result,ic);
10543 pic16_freeAsmop(left, NULL, ic, TRUE);
10547 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10549 /* if the value is already in a pointer register
10550 * then don't need anything more */
10551 if (!AOP_INPREG(AOP(left))) {
10552 /* otherwise get a free pointer register */
10553 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10555 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
10556 /* bitfields will be handled by genUnpackBits */
10557 if(!IS_BITFIELD(retype)) {
10559 if(is_LitAOp( AOP(left) )) {
10560 pic16_loadFSR0( left );
10562 // set up FSR0 with address from left
10563 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10564 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10569 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10571 pic16_aopOp (result,ic,FALSE);
10573 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10575 /* if bitfield then unpack the bits */
10576 if (IS_BITFIELD(retype))
10577 genUnpackBits (result, left, NULL, POINTER);
10579 /* we have can just get the values */
10580 int size = AOP_SIZE(result);
10583 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10585 /* fsr0 is loaded already -- VR */
10586 // pic16_loadFSR0( left );
10588 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
10589 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
10592 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10593 pic16_popGet(AOP(result), offset++)));
10595 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10596 pic16_popGet(AOP(result), offset++)));
10600 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
10601 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
10603 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
10607 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
10609 pic16_emitcode("mov","a,@%s",rname);
10610 pic16_aopPut(AOP(result),"a",offset);
10612 sprintf(buffer,"@%s",rname);
10613 pic16_aopPut(AOP(result),buffer,offset);
10617 pic16_emitcode("inc","%s",rname);
10622 /* now some housekeeping stuff */
10624 /* we had to allocate for this iCode */
10625 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10626 pic16_freeAsmop(NULL,aop,ic,TRUE);
10628 /* we did not allocate which means left
10629 * already in a pointer register, then
10630 * if size > 0 && this could be used again
10631 * we have to point it back to where it
10633 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10634 if (AOP_SIZE(result) > 1
10635 && !OP_SYMBOL(left)->remat
10636 && ( OP_SYMBOL(left)->liveTo > ic->seq
10638 // int size = AOP_SIZE(result) - 1;
10640 // pic16_emitcode("dec","%s",rname);
10645 pic16_freeAsmop(left,NULL,ic,TRUE);
10646 pic16_freeAsmop(result,NULL,ic,TRUE);
10649 /*-----------------------------------------------------------------*/
10650 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10651 /*-----------------------------------------------------------------*/
10652 static void genPagedPointerGet (operand *left,
10657 regs *preg = NULL ;
10659 sym_link *rtype, *retype;
10661 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10663 rtype = operandType(result);
10664 retype= getSpec(rtype);
10666 pic16_aopOp(left,ic,FALSE);
10668 /* if the value is already in a pointer register
10669 then don't need anything more */
10670 if (!AOP_INPREG(AOP(left))) {
10671 /* otherwise get a free pointer register */
10673 preg = getFreePtr(ic,&aop,FALSE);
10674 pic16_emitcode("mov","%s,%s",
10676 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10677 rname = preg->name ;
10679 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10681 pic16_freeAsmop(left,NULL,ic,TRUE);
10682 pic16_aopOp (result,ic,FALSE);
10684 /* if bitfield then unpack the bits */
10685 if (IS_BITFIELD(retype))
10686 genUnpackBits (result,left,rname,PPOINTER);
10688 /* we have can just get the values */
10689 int size = AOP_SIZE(result);
10694 pic16_emitcode("movx","a,@%s",rname);
10695 pic16_aopPut(AOP(result),"a",offset);
10700 pic16_emitcode("inc","%s",rname);
10704 /* now some housekeeping stuff */
10706 /* we had to allocate for this iCode */
10707 pic16_freeAsmop(NULL,aop,ic,TRUE);
10709 /* we did not allocate which means left
10710 already in a pointer register, then
10711 if size > 0 && this could be used again
10712 we have to point it back to where it
10714 if (AOP_SIZE(result) > 1 &&
10715 !OP_SYMBOL(left)->remat &&
10716 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10718 int size = AOP_SIZE(result) - 1;
10720 pic16_emitcode("dec","%s",rname);
10725 pic16_freeAsmop(result,NULL,ic,TRUE);
10730 /*-----------------------------------------------------------------*/
10731 /* genFarPointerGet - gget value from far space */
10732 /*-----------------------------------------------------------------*/
10733 static void genFarPointerGet (operand *left,
10734 operand *result, iCode *ic)
10737 sym_link *retype = getSpec(operandType(result));
10739 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10741 pic16_aopOp(left,ic,FALSE);
10743 /* if the operand is already in dptr
10744 then we do nothing else we move the value to dptr */
10745 if (AOP_TYPE(left) != AOP_STR) {
10746 /* if this is remateriazable */
10747 if (AOP_TYPE(left) == AOP_IMMD)
10748 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10749 else { /* we need to get it byte by byte */
10750 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10751 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10752 if (options.model == MODEL_FLAT24)
10754 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10758 /* so dptr know contains the address */
10759 pic16_freeAsmop(left,NULL,ic,TRUE);
10760 pic16_aopOp(result,ic,FALSE);
10762 /* if bit then unpack */
10763 if (IS_BITFIELD(retype))
10764 genUnpackBits(result,left,"dptr",FPOINTER);
10766 size = AOP_SIZE(result);
10770 pic16_emitcode("movx","a,@dptr");
10771 pic16_aopPut(AOP(result),"a",offset++);
10773 pic16_emitcode("inc","dptr");
10777 pic16_freeAsmop(result,NULL,ic,TRUE);
10780 /*-----------------------------------------------------------------*/
10781 /* genCodePointerGet - get value from code space */
10782 /*-----------------------------------------------------------------*/
10783 static void genCodePointerGet (operand *left,
10784 operand *result, iCode *ic)
10787 sym_link *retype = getSpec(operandType(result));
10789 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10791 pic16_aopOp(left,ic,FALSE);
10793 /* if the operand is already in dptr
10794 then we do nothing else we move the value to dptr */
10795 if (AOP_TYPE(left) != AOP_STR) {
10796 /* if this is remateriazable */
10797 if (AOP_TYPE(left) == AOP_IMMD)
10798 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10799 else { /* we need to get it byte by byte */
10800 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10801 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10802 if (options.model == MODEL_FLAT24)
10804 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10808 /* so dptr know contains the address */
10809 pic16_freeAsmop(left,NULL,ic,TRUE);
10810 pic16_aopOp(result,ic,FALSE);
10812 /* if bit then unpack */
10813 if (IS_BITFIELD(retype))
10814 genUnpackBits(result,left,"dptr",CPOINTER);
10816 size = AOP_SIZE(result);
10820 pic16_emitcode("clr","a");
10821 pic16_emitcode("movc","a,@a+dptr");
10822 pic16_aopPut(AOP(result),"a",offset++);
10824 pic16_emitcode("inc","dptr");
10828 pic16_freeAsmop(result,NULL,ic,TRUE);
10832 /*-----------------------------------------------------------------*/
10833 /* genGenPointerGet - gget value from generic pointer space */
10834 /*-----------------------------------------------------------------*/
10835 static void genGenPointerGet (operand *left,
10836 operand *result, iCode *ic)
10838 int size, offset, lit;
10839 sym_link *retype = getSpec(operandType(result));
10841 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10842 pic16_aopOp(left,ic,FALSE);
10843 pic16_aopOp(result,ic,FALSE);
10844 size = AOP_SIZE(result);
10846 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10848 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10850 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10851 // load FSR0 from immediate
10852 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10854 // pic16_loadFSR0( left );
10859 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10861 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10868 else { /* we need to get it byte by byte */
10869 // set up FSR0 with address from left
10870 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10871 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10877 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10879 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10886 /* if bit then unpack */
10887 if (IS_BITFIELD(retype))
10888 genUnpackBits(result,left,"BAD",GPOINTER);
10891 pic16_freeAsmop(left,NULL,ic,TRUE);
10892 pic16_freeAsmop(result,NULL,ic,TRUE);
10898 /*-----------------------------------------------------------------*/
10899 /* genGenPointerGet - gget value from generic pointer space */
10900 /*-----------------------------------------------------------------*/
10901 static void genGenPointerGet (operand *left,
10902 operand *result, iCode *ic)
10904 int size, offset, lit;
10905 sym_link *retype = getSpec(operandType(result));
10908 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10909 pic16_aopOp(left,ic,FALSE);
10910 pic16_aopOp(result,ic,FALSE);
10911 size = AOP_SIZE(result);
10913 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10915 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
10917 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
10918 // load FSR0 from immediate
10919 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10921 werror(W_POSSBUG2, __FILE__, __LINE__);
10926 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
10928 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
10935 } else { /* we need to get it byte by byte */
10937 /* set up WREG:PRODL:FSR0L with address from left */
10938 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10939 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
10940 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
10943 case 1: strcpy(fgptrget, "__gptrget1"); break;
10944 case 2: strcpy(fgptrget, "__gptrget2"); break;
10945 case 3: strcpy(fgptrget, "__gptrget3"); break;
10946 case 4: strcpy(fgptrget, "__gptrget4"); break;
10948 werror(W_POSSBUG2, __FILE__, __LINE__);
10952 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget ));
10954 assignResultValue(result, 1);
10959 sym = newSymbol( fgptrget, 0 );
10960 strcpy(sym->rname, fgptrget);
10961 checkAddSym(&externs, sym);
10963 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget);
10969 /* if bit then unpack */
10970 if (IS_BITFIELD(retype))
10971 genUnpackBits(result,left,"BAD",GPOINTER);
10974 pic16_freeAsmop(left,NULL,ic,TRUE);
10975 pic16_freeAsmop(result,NULL,ic,TRUE);
10978 /*-----------------------------------------------------------------*/
10979 /* genConstPointerGet - get value from const generic pointer space */
10980 /*-----------------------------------------------------------------*/
10981 static void genConstPointerGet (operand *left,
10982 operand *result, iCode *ic)
10984 //sym_link *retype = getSpec(operandType(result));
10985 // symbol *albl = newiTempLabel(NULL); // patch 15
10986 // symbol *blbl = newiTempLabel(NULL); //
10987 // PIC_OPCODE poc; // patch 15
10991 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10992 pic16_aopOp(left,ic,FALSE);
10993 pic16_aopOp(result,ic,TRUE);
10994 size = AOP_SIZE(result);
10996 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10998 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11000 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
11001 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
11002 pic16_emitpLabel(albl->key);
11004 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
11006 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
11007 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
11008 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
11009 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
11010 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
11012 pic16_emitpLabel(blbl->key);
11014 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
11018 // set up table pointer
11019 if( (AOP_TYPE(left) == AOP_PCODE)
11020 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11021 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
11023 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11024 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11025 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11026 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11027 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11028 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11032 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11033 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11034 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11040 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11041 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11045 pic16_freeAsmop(left,NULL,ic,TRUE);
11046 pic16_freeAsmop(result,NULL,ic,TRUE);
11051 /*-----------------------------------------------------------------*/
11052 /* genPointerGet - generate code for pointer get */
11053 /*-----------------------------------------------------------------*/
11054 static void genPointerGet (iCode *ic)
11056 operand *left, *result ;
11057 sym_link *type, *etype;
11062 left = IC_LEFT(ic);
11063 result = IC_RESULT(ic) ;
11065 /* depending on the type of pointer we need to
11066 move it to the correct pointer register */
11067 type = operandType(left);
11068 etype = getSpec(type);
11071 if (IS_PTR_CONST(type))
11073 if (IS_CODEPTR(type))
11075 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11077 /* if left is of type of pointer then it is simple */
11078 if (IS_PTR(type) && !IS_FUNC(type->next))
11079 p_type = DCL_TYPE(type);
11081 /* we have to go by the storage class */
11082 p_type = PTR_TYPE(SPEC_OCLS(etype));
11084 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11086 if (SPEC_OCLS(etype)->codesp ) {
11087 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11088 //p_type = CPOINTER ;
11091 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
11092 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11093 /*p_type = FPOINTER ;*/
11095 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
11096 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11097 /* p_type = PPOINTER; */
11099 if (SPEC_OCLS(etype) == idata )
11100 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11101 /* p_type = IPOINTER; */
11103 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11104 /* p_type = POINTER ; */
11107 /* now that we have the pointer type we assign
11108 the pointer values */
11113 genNearPointerGet (left,result,ic);
11117 genPagedPointerGet(left,result,ic);
11121 genFarPointerGet (left,result,ic);
11125 genConstPointerGet (left,result,ic);
11126 //pic16_emitcodePointerGet (left,result,ic);
11131 if (IS_PTR_CONST(type))
11132 genConstPointerGet (left,result,ic);
11135 genGenPointerGet (left,result,ic);
11139 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11140 "genPointerGet: illegal pointer type");
11146 /*-----------------------------------------------------------------*/
11147 /* genPackBits - generates code for packed bit storage */
11148 /*-----------------------------------------------------------------*/
11149 static void genPackBits (sym_link *etype , operand *result,
11151 char *rname, int p_type)
11160 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11161 blen = SPEC_BLEN(etype);
11162 bstr = SPEC_BSTR(etype);
11164 retype = getSpec(operandType(right));
11166 if(AOP_TYPE(right) == AOP_LIT) {
11167 if((blen == 1) && (bstr < 8)) {
11169 /* it is a single bit, so use the appropriate bit instructions */
11171 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11173 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11174 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11175 if((p_type == POINTER) && (result)) {
11176 /* workaround to reduce the extra lfsr instruction */
11178 pic16_emitpcode(POC_BSF,
11179 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11181 pic16_emitpcode(POC_BCF,
11182 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11185 pic16_loadFSR0( result );
11187 pic16_emitpcode(POC_BSF,
11188 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11190 pic16_emitpcode(POC_BCF,
11191 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11198 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11201 if(IS_BITFIELD(retype)
11202 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11206 rblen = SPEC_BLEN( retype );
11207 rbstr = SPEC_BSTR( retype );
11210 if(IS_BITFIELD(etype)) {
11211 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11212 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11214 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11217 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11219 if(IS_BITFIELD(etype)) {
11220 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11222 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11225 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11229 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11231 /* if the bit lenth is less than or */
11232 /* it exactly fits a byte then */
11233 if((shCnt=SPEC_BSTR(etype))
11234 || SPEC_BLEN(etype) <= 8 ) {
11236 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11238 /* shift left acc */
11241 /* using PRODL as a temporary register here */
11242 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11247 pic16_loadFSR0( result );
11248 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11249 // pic16_emitcode ("mov","b,a");
11250 // pic16_emitcode("mov","a,@%s",rname);
11254 werror(W_POSSBUG2, __FILE__, __LINE__);
11259 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11260 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11261 (unsigned char)(0xff >> (8-bstr))) ));
11262 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
11263 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11270 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11271 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11276 if ( SPEC_BLEN(etype) <= 8 )
11279 pic16_emitcode("inc","%s",rname);
11280 rLen = SPEC_BLEN(etype) ;
11284 /* now generate for lengths greater than one byte */
11287 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
11297 pic16_emitcode("mov","@%s,a",rname);
11299 pic16_emitcode("mov","@%s,%s",rname,l);
11304 pic16_emitcode("movx","@dptr,a");
11309 DEBUGpic16_emitcode(";lcall","__gptrput");
11312 pic16_emitcode ("inc","%s",rname);
11317 /* last last was not complete */
11319 /* save the byte & read byte */
11322 pic16_emitcode ("mov","b,a");
11323 pic16_emitcode("mov","a,@%s",rname);
11327 pic16_emitcode ("mov","b,a");
11328 pic16_emitcode("movx","a,@dptr");
11332 pic16_emitcode ("push","b");
11333 pic16_emitcode ("push","acc");
11334 pic16_emitcode ("lcall","__gptrget");
11335 pic16_emitcode ("pop","b");
11339 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11340 pic16_emitcode ("orl","a,b");
11343 if (p_type == GPOINTER)
11344 pic16_emitcode("pop","b");
11349 pic16_emitcode("mov","@%s,a",rname);
11353 pic16_emitcode("movx","@dptr,a");
11357 DEBUGpic16_emitcode(";lcall","__gptrput");
11361 /*-----------------------------------------------------------------*/
11362 /* genDataPointerSet - remat pointer to data space */
11363 /*-----------------------------------------------------------------*/
11364 static void genDataPointerSet(operand *right,
11368 int size, offset = 0, resoffset=0 ;
11370 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11371 pic16_aopOp(right,ic,FALSE);
11373 size = AOP_SIZE(right);
11375 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11378 if ( AOP_TYPE(result) == AOP_PCODE) {
11379 fprintf(stderr,"genDataPointerSet %s, %d\n",
11380 AOP(result)->aopu.pcop->name,
11381 (AOP(result)->aopu.pcop->type == PO_DIR)?
11382 PCOR(AOP(result)->aopu.pcop)->instance:
11383 PCOI(AOP(result)->aopu.pcop)->offset);
11387 if(AOP(result)->aopu.pcop->type == PO_DIR)
11388 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11391 if (AOP_TYPE(right) == AOP_LIT) {
11394 if(!IS_FLOAT(operandType( right )))
11395 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11398 unsigned long lit_int;
11402 /* take care if literal is a float */
11403 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11404 lit = info.lit_int;
11407 lit = lit >> (8*offset);
11409 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11410 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11412 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11415 mov2w(AOP(right), offset);
11416 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11422 pic16_freeAsmop(right,NULL,ic,TRUE);
11427 /*-----------------------------------------------------------------*/
11428 /* genNearPointerSet - pic16_emitcode for near pointer put */
11429 /*-----------------------------------------------------------------*/
11430 static void genNearPointerSet (operand *right,
11437 sym_link *ptype = operandType(result);
11438 sym_link *resetype;
11440 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11441 retype= getSpec(operandType(right));
11442 resetype = getSpec(operandType(result));
11444 pic16_aopOp(result,ic,FALSE);
11446 /* if the result is rematerializable &
11447 * in data space & not a bit variable */
11449 /* and result is not a bit variable */
11450 if (AOP_TYPE(result) == AOP_PCODE
11451 // && AOP_TYPE(result) == AOP_IMMD
11452 && DCL_TYPE(ptype) == POINTER
11453 && !IS_BITFIELD(retype)
11454 && !IS_BITFIELD(resetype)) {
11456 genDataPointerSet (right,result,ic);
11457 pic16_freeAsmop(result,NULL,ic,TRUE);
11461 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11462 pic16_aopOp(right,ic,FALSE);
11463 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11465 /* if the value is already in a pointer register
11466 * then don't need anything more */
11467 if (!AOP_INPREG(AOP(result))) {
11468 /* otherwise get a free pointer register */
11469 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11471 // if( (AOP_TYPE(result) == AOP_PCODE)
11472 // && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
11473 // || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
11474 if(is_LitAOp( AOP(result) ))
11476 if(!IS_BITFIELD(resetype))
11477 pic16_loadFSR0( result ); // patch 10
11479 if(!IS_BITFIELD(resetype)) {
11480 // set up FSR0 with address of result
11481 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
11482 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
11488 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11490 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11492 // pic16_loadFSR0( result );
11494 /* if bitfield then unpack the bits */
11495 if (IS_BITFIELD(resetype)) {
11496 genPackBits (resetype, result, right, NULL, POINTER);
11498 /* we have can just get the values */
11499 int size = AOP_SIZE(right);
11502 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11504 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11507 //pic16_emitcode("mov","@%s,a",rname);
11508 pic16_emitcode("movf","indf0,w ;1");
11511 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
11512 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
11514 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
11516 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
11518 } else { // no literal //
11520 pic16_emitpcode(POC_MOVFF, //
11521 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
11522 pic16_popCopyReg(&pic16_pc_postinc0))); //
11524 pic16_emitpcode(POC_MOVFF, //
11525 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
11526 pic16_popCopyReg(&pic16_pc_indf0))); //
11534 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11535 /* now some housekeeping stuff */
11537 /* we had to allocate for this iCode */
11538 pic16_freeAsmop(NULL,aop,ic,TRUE);
11540 /* we did not allocate which means left
11541 * already in a pointer register, then
11542 * if size > 0 && this could be used again
11543 * we have to point it back to where it
11545 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11546 if (AOP_SIZE(right) > 1
11547 && !OP_SYMBOL(result)->remat
11548 && ( OP_SYMBOL(result)->liveTo > ic->seq
11551 int size = AOP_SIZE(right) - 1;
11554 pic16_emitcode("decf","fsr0,f");
11555 //pic16_emitcode("dec","%s",rname);
11559 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11562 pic16_freeAsmop(right,NULL,ic,TRUE);
11563 pic16_freeAsmop(result,NULL,ic,TRUE);
11566 /*-----------------------------------------------------------------*/
11567 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11568 /*-----------------------------------------------------------------*/
11569 static void genPagedPointerSet (operand *right,
11574 regs *preg = NULL ;
11578 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11580 retype= getSpec(operandType(right));
11582 pic16_aopOp(result,ic,FALSE);
11584 /* if the value is already in a pointer register
11585 then don't need anything more */
11586 if (!AOP_INPREG(AOP(result))) {
11587 /* otherwise get a free pointer register */
11589 preg = getFreePtr(ic,&aop,FALSE);
11590 pic16_emitcode("mov","%s,%s",
11592 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11593 rname = preg->name ;
11595 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11597 pic16_freeAsmop(result,NULL,ic,TRUE);
11598 pic16_aopOp (right,ic,FALSE);
11600 /* if bitfield then unpack the bits */
11601 if (IS_BITFIELD(retype))
11602 genPackBits (retype,result,right,rname,PPOINTER);
11604 /* we have can just get the values */
11605 int size = AOP_SIZE(right);
11609 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11612 pic16_emitcode("movx","@%s,a",rname);
11615 pic16_emitcode("inc","%s",rname);
11621 /* now some housekeeping stuff */
11623 /* we had to allocate for this iCode */
11624 pic16_freeAsmop(NULL,aop,ic,TRUE);
11626 /* we did not allocate which means left
11627 already in a pointer register, then
11628 if size > 0 && this could be used again
11629 we have to point it back to where it
11631 if (AOP_SIZE(right) > 1 &&
11632 !OP_SYMBOL(result)->remat &&
11633 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11635 int size = AOP_SIZE(right) - 1;
11637 pic16_emitcode("dec","%s",rname);
11642 pic16_freeAsmop(right,NULL,ic,TRUE);
11647 /*-----------------------------------------------------------------*/
11648 /* genFarPointerSet - set value from far space */
11649 /*-----------------------------------------------------------------*/
11650 static void genFarPointerSet (operand *right,
11651 operand *result, iCode *ic)
11654 sym_link *retype = getSpec(operandType(right));
11656 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11657 pic16_aopOp(result,ic,FALSE);
11659 /* if the operand is already in dptr
11660 then we do nothing else we move the value to dptr */
11661 if (AOP_TYPE(result) != AOP_STR) {
11662 /* if this is remateriazable */
11663 if (AOP_TYPE(result) == AOP_IMMD)
11664 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11665 else { /* we need to get it byte by byte */
11666 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11667 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11668 if (options.model == MODEL_FLAT24)
11670 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11674 /* so dptr know contains the address */
11675 pic16_freeAsmop(result,NULL,ic,TRUE);
11676 pic16_aopOp(right,ic,FALSE);
11678 /* if bit then unpack */
11679 if (IS_BITFIELD(retype))
11680 genPackBits(retype,result,right,"dptr",FPOINTER);
11682 size = AOP_SIZE(right);
11686 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11688 pic16_emitcode("movx","@dptr,a");
11690 pic16_emitcode("inc","dptr");
11694 pic16_freeAsmop(right,NULL,ic,TRUE);
11697 /*-----------------------------------------------------------------*/
11698 /* genGenPointerSet - set value from generic pointer space */
11699 /*-----------------------------------------------------------------*/
11701 static void genGenPointerSet (operand *right,
11702 operand *result, iCode *ic)
11704 int i, size, offset, lit;
11705 sym_link *retype = getSpec(operandType(right));
11707 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11709 pic16_aopOp(result,ic,FALSE);
11710 pic16_aopOp(right,ic,FALSE);
11711 size = AOP_SIZE(right);
11714 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11716 /* if the operand is already in dptr
11717 then we do nothing else we move the value to dptr */
11718 if (AOP_TYPE(result) != AOP_STR) {
11719 /* if this is remateriazable */
11720 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11721 // WARNING: anythig until "else" is untested!
11722 if (AOP_TYPE(result) == AOP_IMMD) {
11723 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11724 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11725 // load FSR0 from immediate
11726 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11730 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11732 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11738 else { /* we need to get it byte by byte */
11739 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11740 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11742 // set up FSR0 with address of result
11743 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11744 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11746 /* hack hack! see if this the FSR. If so don't load W */
11747 if(AOP_TYPE(right) != AOP_ACC) {
11749 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11751 if(AOP_TYPE(right) == AOP_LIT)
11754 // note: pic16_popGet handles sign extension
11755 for(i=0;i<size;i++) {
11756 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11758 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11760 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11765 for(i=0;i<size;i++) {
11767 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11768 pic16_popCopyReg(&pic16_pc_postinc0)));
11770 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11771 pic16_popCopyReg(&pic16_pc_indf0)));
11777 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11778 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11780 } // if (AOP_TYPE(result) != AOP_IMMD)
11782 } // if (AOP_TYPE(result) != AOP_STR)
11783 /* so dptr know contains the address */
11786 /* if bit then unpack */
11787 if (IS_BITFIELD(retype))
11788 genPackBits(retype,result,right,"dptr",GPOINTER);
11790 size = AOP_SIZE(right);
11793 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11795 // set up FSR0 with address of result
11796 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11797 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11800 if (AOP_TYPE(right) == AOP_LIT) {
11801 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11803 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11805 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11807 } else { // no literal
11809 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11811 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11819 pic16_freeAsmop(right,NULL,ic,TRUE);
11820 pic16_freeAsmop(result,NULL,ic,TRUE);
11824 static void genGenPointerSet (operand *right,
11825 operand *result, iCode *ic)
11828 sym_link *retype = getSpec(operandType(right));
11831 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11833 pic16_aopOp(result,ic,FALSE);
11834 pic16_aopOp(right,ic,FALSE);
11835 size = AOP_SIZE(right);
11837 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11840 /* if bit then unpack */
11841 if (IS_BITFIELD(retype)) {
11842 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11843 genPackBits(retype,result,right,"dptr",GPOINTER);
11847 size = AOP_SIZE(right);
11849 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11853 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11855 /* value of right+0 is placed on stack, which will be retrieved
11856 * by the support function this restoring the stack. The important
11857 * thing is that there is no need to manually restore stack pointer
11859 pushaop(AOP(right), 0);
11860 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11861 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11862 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11863 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
11865 /* load address to write to in WREG:FSR0H:FSR0L */
11866 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
11867 pic16_popCopyReg(&pic16_pc_fsr0l)));
11868 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
11869 pic16_popCopyReg(&pic16_pc_prodl)));
11870 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
11873 /* put code here */
11875 case 1: strcpy(fgptrput, "__gptrput1"); break;
11876 case 2: strcpy(fgptrput, "__gptrput2"); break;
11877 case 3: strcpy(fgptrput, "__gptrput3"); break;
11878 case 4: strcpy(fgptrput, "__gptrput4"); break;
11880 werror(W_POSSBUG2, __FILE__, __LINE__);
11884 pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput ));
11889 sym = newSymbol( fgptrput, 0 );
11890 strcpy(sym->rname, fgptrput);
11891 checkAddSym(&externs, sym);
11895 pic16_freeAsmop(right,NULL,ic,TRUE);
11896 pic16_freeAsmop(result,NULL,ic,TRUE);
11899 /*-----------------------------------------------------------------*/
11900 /* genPointerSet - stores the value into a pointer location */
11901 /*-----------------------------------------------------------------*/
11902 static void genPointerSet (iCode *ic)
11904 operand *right, *result ;
11905 sym_link *type, *etype;
11910 right = IC_RIGHT(ic);
11911 result = IC_RESULT(ic) ;
11913 /* depending on the type of pointer we need to
11914 move it to the correct pointer register */
11915 type = operandType(result);
11916 etype = getSpec(type);
11917 /* if left is of type of pointer then it is simple */
11918 if (IS_PTR(type) && !IS_FUNC(type->next)) {
11919 p_type = DCL_TYPE(type);
11922 /* we have to go by the storage class */
11923 p_type = PTR_TYPE(SPEC_OCLS(etype));
11925 /* if (SPEC_OCLS(etype)->codesp ) { */
11926 /* p_type = CPOINTER ; */
11929 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11930 /* p_type = FPOINTER ; */
11932 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11933 /* p_type = PPOINTER ; */
11935 /* if (SPEC_OCLS(etype) == idata ) */
11936 /* p_type = IPOINTER ; */
11938 /* p_type = POINTER ; */
11941 /* now that we have the pointer type we assign
11942 the pointer values */
11947 genNearPointerSet (right,result,ic);
11951 genPagedPointerSet (right,result,ic);
11955 genFarPointerSet (right,result,ic);
11959 genGenPointerSet (right,result,ic);
11963 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11964 "genPointerSet: illegal pointer type");
11968 /*-----------------------------------------------------------------*/
11969 /* genIfx - generate code for Ifx statement */
11970 /*-----------------------------------------------------------------*/
11971 static void genIfx (iCode *ic, iCode *popIc)
11973 operand *cond = IC_COND(ic);
11978 pic16_aopOp(cond,ic,FALSE);
11980 /* get the value into acc */
11981 if (AOP_TYPE(cond) != AOP_CRY)
11982 pic16_toBoolean(cond);
11985 /* the result is now in the accumulator */
11986 pic16_freeAsmop(cond,NULL,ic,TRUE);
11988 /* if there was something to be popped then do it */
11992 /* if the condition is a bit variable */
11993 if (isbit && IS_ITEMP(cond) &&
11995 genIfxJump(ic,SPIL_LOC(cond)->rname);
11996 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
11998 if (isbit && !IS_ITEMP(cond))
11999 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12001 genIfxJump(ic,"a");
12006 /*-----------------------------------------------------------------*/
12007 /* genAddrOf - generates code for address of */
12008 /*-----------------------------------------------------------------*/
12009 static void genAddrOf (iCode *ic)
12011 operand *result, *left;
12013 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12014 pCodeOp *pcop0, *pcop1, *pcop2;
12018 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12020 sym = OP_SYMBOL( IC_LEFT(ic) );
12023 /* get address of symbol on stack */
12024 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12026 fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__,
12027 OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack);
12030 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
12031 pic16_popCopyReg(&pic16_pc_fsr2l),
12032 pic16_popGet(AOP(result), 0)));
12033 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
12034 pic16_popCopyReg(&pic16_pc_fsr2h),
12035 pic16_popGet(AOP(result), 1)));
12037 // operands on stack are accessible via "FSR2 - index" with index starting at 0 for the first operand
12038 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( - (OP_SYMBOL( IC_LEFT(ic))->stack + 1 ) /*+ _G.stack_lat*/));
12039 pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(result), 0));
12041 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result), 1));
12046 // if(pic16_debug_verbose) {
12047 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12048 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12051 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12052 size = AOP_SIZE(IC_RESULT(ic));
12055 /* Assume that what we want the address of is in data space
12056 * since there is no stack on the PIC, yet! -- VR */
12058 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12059 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12060 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12063 pic16_emitpcode(POC_MOVLW, pcop0);
12064 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12065 pic16_emitpcode(POC_MOVLW, pcop1);
12066 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12067 pic16_emitpcode(POC_MOVLW, pcop2);
12068 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12071 pic16_emitpcode(POC_MOVLW, pcop0);
12072 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12073 pic16_emitpcode(POC_MOVLW, pcop1);
12074 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12076 pic16_emitpcode(POC_MOVLW, pcop0);
12077 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12080 pic16_freeAsmop(left, NULL, ic, FALSE);
12082 pic16_freeAsmop(result,NULL,ic,TRUE);
12087 /*-----------------------------------------------------------------*/
12088 /* genFarFarAssign - assignment when both are in far space */
12089 /*-----------------------------------------------------------------*/
12090 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12092 int size = AOP_SIZE(right);
12095 /* first push the right side on to the stack */
12097 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12099 pic16_emitcode ("push","acc");
12102 pic16_freeAsmop(right,NULL,ic,FALSE);
12103 /* now assign DPTR to result */
12104 pic16_aopOp(result,ic,FALSE);
12105 size = AOP_SIZE(result);
12107 pic16_emitcode ("pop","acc");
12108 pic16_aopPut(AOP(result),"a",--offset);
12110 pic16_freeAsmop(result,NULL,ic,FALSE);
12115 /*-----------------------------------------------------------------*/
12116 /* genAssign - generate code for assignment */
12117 /*-----------------------------------------------------------------*/
12118 static void genAssign (iCode *ic)
12120 operand *result, *right;
12121 int size, offset,know_W;
12122 unsigned long lit = 0L;
12124 result = IC_RESULT(ic);
12125 right = IC_RIGHT(ic) ;
12129 /* if they are the same */
12130 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12133 /* reversed order operands are aopOp'ed so that result operand
12134 * is effective in case right is a stack symbol. This maneauver
12135 * allows to use the _G.resDirect flag later */
12136 pic16_aopOp(result,ic,TRUE);
12137 pic16_aopOp(right,ic,FALSE);
12139 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12141 /* if they are the same registers */
12142 if (pic16_sameRegs(AOP(right),AOP(result)))
12145 /* if the result is a bit */
12146 if (AOP_TYPE(result) == AOP_CRY) {
12147 /* if the right size is a literal then
12148 we know what the value is */
12149 if (AOP_TYPE(right) == AOP_LIT) {
12151 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12152 pic16_popGet(AOP(result),0));
12154 if (((int) operandLitValue(right)))
12155 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12156 AOP(result)->aopu.aop_dir,
12157 AOP(result)->aopu.aop_dir);
12159 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12160 AOP(result)->aopu.aop_dir,
12161 AOP(result)->aopu.aop_dir);
12165 /* the right is also a bit variable */
12166 if (AOP_TYPE(right) == AOP_CRY) {
12167 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12168 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12169 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12171 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12172 AOP(result)->aopu.aop_dir,
12173 AOP(result)->aopu.aop_dir);
12174 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12175 AOP(right)->aopu.aop_dir,
12176 AOP(right)->aopu.aop_dir);
12177 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12178 AOP(result)->aopu.aop_dir,
12179 AOP(result)->aopu.aop_dir);
12183 /* we need to or */
12184 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12185 pic16_toBoolean(right);
12187 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12188 //pic16_aopPut(AOP(result),"a",0);
12192 /* bit variables done */
12194 size = AOP_SIZE(result);
12197 if(AOP_TYPE(right) == AOP_LIT) {
12198 if(!IS_FLOAT(operandType( right )))
12199 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12202 unsigned long lit_int;
12206 /* take care if literal is a float */
12207 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12208 lit = info.lit_int;
12212 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12213 // sizeof(unsigned long int), sizeof(float));
12216 if (AOP_TYPE(right) == AOP_REG) {
12217 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12220 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12225 if(AOP_TYPE(right) != AOP_LIT
12226 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12227 && !IS_FUNC(OP_SYM_TYPE(right))
12229 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12230 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12232 // set up table pointer
12233 if(is_LitOp(right)) {
12234 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12235 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12236 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12237 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12238 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12239 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12240 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12242 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12243 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12244 pic16_popCopyReg(&pic16_pc_tblptrl)));
12245 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12246 pic16_popCopyReg(&pic16_pc_tblptrh)));
12247 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12248 pic16_popCopyReg(&pic16_pc_tblptru)));
12251 size = min(AOP_SIZE(right), AOP_SIZE(result));
12253 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12254 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12255 pic16_popGet(AOP(result),offset)));
12259 if(AOP_SIZE(result) > AOP_SIZE(right)) {
12260 size = AOP_SIZE(result) - AOP_SIZE(right);
12262 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12272 /* VR - What is this?! */
12273 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12274 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12275 if(aopIdx(AOP(result),0) == 4) {
12277 /* this is a workaround to save value of right into wreg too,
12278 * value of wreg is going to be used later */
12279 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12280 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12281 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12285 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12291 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12292 if(AOP_TYPE(right) == AOP_LIT) {
12294 if(know_W != (lit&0xff))
12295 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12297 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12299 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12303 } else if (AOP_TYPE(right) == AOP_CRY) {
12304 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12306 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12307 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12308 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12310 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12311 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12312 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12314 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12316 if(!_G.resDirect) /* use this aopForSym feature */
12317 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12324 pic16_freeAsmop (right,NULL,ic,FALSE);
12325 pic16_freeAsmop (result,NULL,ic,TRUE);
12328 /*-----------------------------------------------------------------*/
12329 /* genJumpTab - generates code for jump table */
12330 /*-----------------------------------------------------------------*/
12331 static void genJumpTab (iCode *ic)
12336 pCodeOp *jt_offs_hi;
12341 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12342 /* get the condition into accumulator */
12343 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12345 /* multiply by three */
12346 pic16_emitcode("add","a,acc");
12347 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12349 jtab = newiTempLabel(NULL);
12350 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12351 pic16_emitcode("jmp","@a+dptr");
12352 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12355 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12356 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12358 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12359 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12360 pic16_emitpLabel(jtab->key);
12364 jt_offs = pic16_popGetTempReg(0);
12365 jt_offs_hi = pic16_popGetTempReg(1);
12366 jt_label = pic16_popGetLabel (jtab->key);
12367 //fprintf (stderr, "Creating jump table...\n");
12369 // calculate offset into jump table (idx * sizeof (GOTO))
12370 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12371 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12372 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12373 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12374 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12375 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12376 pic16_emitpcode(POC_MOVWF , jt_offs);
12378 // prepare PCLATx (set to first entry in jump table)
12379 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12380 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12381 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12382 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12383 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12385 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12386 pic16_emitpcode(POC_ADDWF , jt_offs);
12387 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12388 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12390 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12392 // release temporaries and prepare jump into table (new PCL --> WREG)
12393 pic16_emitpcode(POC_MOVFW , jt_offs);
12394 pic16_popReleaseTempReg (jt_offs_hi, 1);
12395 pic16_popReleaseTempReg (jt_offs, 0);
12397 // jump into the table
12398 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12400 pic16_emitpLabelFORCE(jtab->key);
12403 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12405 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12406 /* now generate the jump labels */
12407 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12408 jtab = setNextItem(IC_JTLABELS(ic))) {
12409 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12410 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12413 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12417 /*-----------------------------------------------------------------*/
12418 /* genMixedOperation - gen code for operators between mixed types */
12419 /*-----------------------------------------------------------------*/
12421 TSD - Written for the PIC port - but this unfortunately is buggy.
12422 This routine is good in that it is able to efficiently promote
12423 types to different (larger) sizes. Unfortunately, the temporary
12424 variables that are optimized out by this routine are sometimes
12425 used in other places. So until I know how to really parse the
12426 iCode tree, I'm going to not be using this routine :(.
12428 static int genMixedOperation (iCode *ic)
12431 operand *result = IC_RESULT(ic);
12432 sym_link *ctype = operandType(IC_LEFT(ic));
12433 operand *right = IC_RIGHT(ic);
12439 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12441 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12447 nextright = IC_RIGHT(nextic);
12448 nextleft = IC_LEFT(nextic);
12449 nextresult = IC_RESULT(nextic);
12451 pic16_aopOp(right,ic,FALSE);
12452 pic16_aopOp(result,ic,FALSE);
12453 pic16_aopOp(nextright, nextic, FALSE);
12454 pic16_aopOp(nextleft, nextic, FALSE);
12455 pic16_aopOp(nextresult, nextic, FALSE);
12457 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12459 operand *t = right;
12463 pic16_emitcode(";remove right +","");
12465 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12467 operand *t = right;
12471 pic16_emitcode(";remove left +","");
12475 big = AOP_SIZE(nextleft);
12476 small = AOP_SIZE(nextright);
12478 switch(nextic->op) {
12481 pic16_emitcode(";optimize a +","");
12482 /* if unsigned or not an integral type */
12483 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12484 pic16_emitcode(";add a bit to something","");
12487 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12489 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12490 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12491 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12493 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12501 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12502 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12503 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12506 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12508 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12509 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12510 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12511 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12512 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12515 pic16_emitcode("rlf","known_zero,w");
12522 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12523 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12524 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12526 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12536 pic16_freeAsmop(right,NULL,ic,TRUE);
12537 pic16_freeAsmop(result,NULL,ic,TRUE);
12538 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12539 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12541 nextic->generated = 1;
12548 /*-----------------------------------------------------------------*/
12549 /* genCast - gen code for casting */
12550 /*-----------------------------------------------------------------*/
12551 static void genCast (iCode *ic)
12553 operand *result = IC_RESULT(ic);
12554 sym_link *ctype = operandType(IC_LEFT(ic));
12555 sym_link *rtype = operandType(IC_RIGHT(ic));
12556 sym_link *restype = operandType(IC_RESULT(ic));
12557 operand *right = IC_RIGHT(ic);
12563 /* if they are equivalent then do nothing */
12564 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12567 pic16_aopOp(right,ic,FALSE) ;
12568 pic16_aopOp(result,ic,FALSE);
12570 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12573 /* if the result is a bit */
12574 if (AOP_TYPE(result) == AOP_CRY) {
12576 /* if the right size is a literal then
12577 * we know what the value is */
12578 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12580 if (AOP_TYPE(right) == AOP_LIT) {
12581 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12582 pic16_popGet(AOP(result),0));
12584 if (((int) operandLitValue(right)))
12585 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12586 AOP(result)->aopu.aop_dir,
12587 AOP(result)->aopu.aop_dir);
12589 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12590 AOP(result)->aopu.aop_dir,
12591 AOP(result)->aopu.aop_dir);
12595 /* the right is also a bit variable */
12596 if (AOP_TYPE(right) == AOP_CRY) {
12598 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12600 pic16_emitcode("clrc","");
12601 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12602 AOP(right)->aopu.aop_dir,
12603 AOP(right)->aopu.aop_dir);
12604 pic16_aopPut(AOP(result),"c",0);
12608 /* we need to or */
12609 if (AOP_TYPE(right) == AOP_REG) {
12610 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12611 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12612 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12614 pic16_toBoolean(right);
12615 pic16_aopPut(AOP(result),"a",0);
12619 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12622 size = AOP_SIZE(result);
12624 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12626 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12627 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12628 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12631 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12636 if(IS_BITFIELD(getSpec(restype))
12637 && IS_BITFIELD(getSpec(rtype))) {
12638 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12641 /* if they are the same size : or less */
12642 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12644 /* if they are in the same place */
12645 if (pic16_sameRegs(AOP(right),AOP(result)))
12648 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12650 if (IS_PTR_CONST(rtype))
12652 if (IS_CODEPTR(rtype))
12654 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12657 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12659 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12661 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12664 if(AOP_TYPE(right) == AOP_IMMD) {
12665 pCodeOp *pcop0, *pcop1, *pcop2;
12666 symbol *sym = OP_SYMBOL( right );
12668 size = AOP_SIZE(result);
12670 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12672 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12674 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12677 pic16_emitpcode(POC_MOVLW, pcop0);
12678 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12679 pic16_emitpcode(POC_MOVLW, pcop1);
12680 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12681 pic16_emitpcode(POC_MOVLW, pcop2);
12682 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12685 pic16_emitpcode(POC_MOVLW, pcop0);
12686 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12687 pic16_emitpcode(POC_MOVLW, pcop1);
12688 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12690 pic16_emitpcode(POC_MOVLW, pcop0);
12691 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12695 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12696 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12697 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12698 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12699 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12700 if(AOP_SIZE(result) <2)
12701 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12703 /* if they in different places then copy */
12704 size = AOP_SIZE(result);
12707 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12708 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12715 /* if the result is of type pointer */
12716 if (IS_PTR(ctype)) {
12718 sym_link *type = operandType(right);
12719 sym_link *etype = getSpec(type);
12721 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12723 /* pointer to generic pointer */
12724 if (IS_GENPTR(ctype)) {
12728 p_type = DCL_TYPE(type);
12730 /* we have to go by the storage class */
12731 p_type = PTR_TYPE(SPEC_OCLS(etype));
12733 /* if (SPEC_OCLS(etype)->codesp ) */
12734 /* p_type = CPOINTER ; */
12736 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12737 /* p_type = FPOINTER ; */
12739 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12740 /* p_type = PPOINTER; */
12742 /* if (SPEC_OCLS(etype) == idata ) */
12743 /* p_type = IPOINTER ; */
12745 /* p_type = POINTER ; */
12748 /* the first two bytes are known */
12749 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
12750 size = GPTRSIZE - 1;
12753 if(offset < AOP_SIZE(right)) {
12754 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12755 mov2f(AOP(result), AOP(right), offset);
12757 if ((AOP_TYPE(right) == AOP_PCODE) &&
12758 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12759 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12760 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12763 pic16_aopPut(AOP(result),
12764 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12769 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12772 /* the last byte depending on type */
12776 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12777 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12778 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12782 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12786 pic16_emitcode(";BUG!? ","%d",__LINE__);
12790 pic16_emitcode(";BUG!? ","%d",__LINE__);
12795 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12799 /* this should never happen */
12800 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12801 "got unknown pointer type");
12804 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
12808 /* just copy the pointers */
12809 size = AOP_SIZE(result);
12812 pic16_aopPut(AOP(result),
12813 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12822 /* so we now know that the size of destination is greater
12823 than the size of the source.
12824 Now, if the next iCode is an operator then we might be
12825 able to optimize the operation without performing a cast.
12827 if(genMixedOperation(ic))
12830 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12832 /* we move to result for the size of source */
12833 size = AOP_SIZE(right);
12836 mov2f(AOP(result), AOP(right), offset);
12840 /* now depending on the sign of the destination */
12841 size = AOP_SIZE(result) - AOP_SIZE(right);
12842 /* if unsigned or not an integral type */
12843 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
12845 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12847 /* we need to extend the sign :( */
12850 /* Save one instruction of casting char to int */
12851 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12852 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12853 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
12855 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
12858 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12860 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12862 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
12865 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
12870 pic16_freeAsmop(right,NULL,ic,TRUE);
12871 pic16_freeAsmop(result,NULL,ic,TRUE);
12875 /*-----------------------------------------------------------------*/
12876 /* genDjnz - generate decrement & jump if not zero instrucion */
12877 /*-----------------------------------------------------------------*/
12878 static int genDjnz (iCode *ic, iCode *ifx)
12880 symbol *lbl, *lbl1;
12881 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12886 /* if the if condition has a false label
12887 then we cannot save */
12891 /* if the minus is not of the form
12893 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
12894 !IS_OP_LITERAL(IC_RIGHT(ic)))
12897 if (operandLitValue(IC_RIGHT(ic)) != 1)
12900 /* if the size of this greater than one then no
12902 if (getSize(operandType(IC_RESULT(ic))) > 1)
12905 /* otherwise we can save BIG */
12906 lbl = newiTempLabel(NULL);
12907 lbl1= newiTempLabel(NULL);
12909 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
12911 if (IS_AOP_PREG(IC_RESULT(ic))) {
12912 pic16_emitcode("dec","%s",
12913 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12914 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12915 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
12919 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
12920 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
12922 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
12923 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
12927 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12928 ifx->generated = 1;
12932 /*-----------------------------------------------------------------*/
12933 /* genReceive - generate code for a receive iCode */
12934 /*-----------------------------------------------------------------*/
12935 static void genReceive (iCode *ic)
12941 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
12942 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
12944 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
12946 if (isOperandInFarSpace(IC_RESULT(ic))
12947 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
12948 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
12950 int size = getSize(operandType(IC_RESULT(ic)));
12951 int offset = pic16_fReturnSizePic - size;
12955 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
12956 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
12960 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
12962 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
12963 size = AOP_SIZE(IC_RESULT(ic));
12966 pic16_emitcode ("pop","acc");
12967 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
12970 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
12972 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
12975 /* set pseudo stack pointer to where it should be - dw*/
12976 GpsuedoStkPtr = ic->parmBytes;
12978 /* setting GpsuedoStkPtr has side effects here: */
12979 assignResultValue(IC_RESULT(ic), 0);
12982 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
12985 /*-----------------------------------------------------------------*/
12986 /* genDummyRead - generate code for dummy read of volatiles */
12987 /*-----------------------------------------------------------------*/
12989 genDummyRead (iCode * ic)
12991 pic16_emitcode ("; genDummyRead","");
12992 pic16_emitcode ("; not implemented","");
12997 /*-----------------------------------------------------------------*/
12998 /* genpic16Code - generate code for pic16 based controllers */
12999 /*-----------------------------------------------------------------*/
13001 * At this point, ralloc.c has gone through the iCode and attempted
13002 * to optimize in a way suitable for a PIC. Now we've got to generate
13003 * PIC instructions that correspond to the iCode.
13005 * Once the instructions are generated, we'll pass through both the
13006 * peep hole optimizer and the pCode optimizer.
13007 *-----------------------------------------------------------------*/
13009 void genpic16Code (iCode *lic)
13014 lineHead = lineCurr = NULL;
13016 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13017 pic16_addpBlock(pb);
13020 /* if debug information required */
13021 if (options.debug && currFunc) {
13023 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13028 for (ic = lic ; ic ; ic = ic->next ) {
13030 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
13031 if ( cln != ic->lineno ) {
13032 if ( options.debug ) {
13033 debugFile->writeCLine (ic);
13036 if(!options.noCcodeInAsm) {
13037 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13038 printCLine(ic->filename, ic->lineno)));
13044 if(options.iCodeInAsm) {
13047 /* insert here code to print iCode as comment */
13048 l = Safe_strdup(printILine(ic));
13049 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13052 /* if the result is marked as
13053 * spilt and rematerializable or code for
13054 * this has already been generated then
13056 if (resultRemat(ic) || ic->generated )
13059 /* depending on the operation */
13078 /* IPOP happens only when trying to restore a
13079 * spilt live range, if there is an ifx statement
13080 * following this pop then the if statement might
13081 * be using some of the registers being popped which
13082 * would destroy the contents of the register so
13083 * we need to check for this condition and handle it */
13085 && ic->next->op == IFX
13086 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13087 genIfx (ic->next,ic);
13105 genEndFunction (ic);
13121 pic16_genPlus (ic) ;
13125 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13126 pic16_genMinus (ic);
13142 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13146 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13152 /* note these two are xlated by algebraic equivalence
13153 * during parsing SDCC.y */
13154 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13155 "got '>=' or '<=' shouldn't have come here");
13159 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13171 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13175 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13179 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13203 genRightShift (ic);
13206 case GET_VALUE_AT_ADDRESS:
13211 if (POINTER_SET(ic))
13238 addSet(&_G.sendSet,ic);
13241 case DUMMY_READ_VOLATILE:
13251 /* now we are ready to call the
13252 peep hole optimizer */
13253 if (!options.nopeep)
13254 peepHole (&lineHead);
13256 /* now do the actual printing */
13257 printLine (lineHead, codeOutFile);
13260 DFPRINTF((stderr,"printing pBlock\n\n"));
13261 pic16_printpBlock(stdout,pb);