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)
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 mov2w (asmop *aop, int offset);
61 static int aopIdx (asmop *aop, int offset);
63 static int labelOffset=0;
64 extern int pic16_debug_verbose;
65 static int optimized_for_speed = 0;
71 /* max_key keeps track of the largest label number used in
72 a function. This is then used to adjust the label offset
73 for the next function.
76 static int GpsuedoStkPtr=0;
78 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
79 unsigned int pic16aopLiteral (value *val, int offset);
80 const char *pic16_AopType(short type);
81 static iCode *ifxForOp ( operand *op, iCode *ic );
83 void pic16_pushpCodeOp(pCodeOp *pcop);
84 void pic16_poppCodeOp(pCodeOp *pcop);
86 static bool is_LitOp(operand *op);
87 static bool is_LitAOp(asmop *aop);
90 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
92 /* this is the down and dirty file with all kinds of
93 kludgy & hacky stuff. This is what it is all about
94 CODE GENERATION for a specific MCU . some of the
95 routines may be reusable, will have to see */
97 static char *zero = "#0x00";
98 static char *one = "#0x01";
99 static char *spname = "sp";
103 * Function return value policy (MSB-->LSB):
105 * 16 bits -> PRODL:WREG
106 * 24 bits -> PRODH:PRODL:WREG
107 * 32 bits -> FSR0L:PRODH:PRODL:WREG
108 * >32 bits -> on stack, and FSR0 points to the beginning
113 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
114 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
115 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
116 static char **fReturn = fReturnpic16;
118 static char *accUse[] = {"WREG"};
120 //static short rbank = -1;
133 /* Resolved ifx structure. This structure stores information
134 about an iCode ifx that makes it easier to generate code.
136 typedef struct resolvedIfx {
137 symbol *lbl; /* pointer to a label */
138 int condition; /* true or false ifx */
139 int generated; /* set true when the code associated with the ifx
143 extern int pic16_ptrRegReq ;
144 extern int pic16_nRegs;
145 extern FILE *codeOutFile;
146 static void saverbank (int, iCode *,bool);
148 static lineNode *lineHead = NULL;
149 static lineNode *lineCurr = NULL;
151 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
152 0xE0, 0xC0, 0x80, 0x00};
153 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
154 0x07, 0x03, 0x01, 0x00};
158 /*-----------------------------------------------------------------*/
159 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
160 /* exponent of 2 is returned, otherwise -1 is */
162 /* note that this is similar to the function `powof2' in SDCCsymt */
166 /*-----------------------------------------------------------------*/
167 static int my_powof2 (unsigned long num)
170 if( (num & (num-1)) == 0) {
183 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
185 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
187 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
188 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
189 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
190 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
191 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
192 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
193 ((result) ? AOP_SIZE(result) : 0));
196 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
199 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
201 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
202 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
203 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
204 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
205 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
206 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
210 void pic16_emitpcomment (char *fmt, ...)
213 char lb[INITIAL_INLINEASM];
219 vsprintf(lb+1,fmt,ap);
221 while (isspace(*lbp)) lbp++;
224 lineCurr = (lineCurr ?
225 connectLine(lineCurr,newLineNode(lb)) :
226 (lineHead = newLineNode(lb)));
227 lineCurr->isInline = _G.inLine;
228 lineCurr->isDebug = _G.debugLine;
230 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
233 // fprintf(stderr, "%s\n", lb);
236 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
239 char lb[INITIAL_INLINEASM];
242 if(!pic16_debug_verbose)
249 sprintf(lb,"%s\t",inst);
251 sprintf(lb,"%s",inst);
252 vsprintf(lb+(strlen(lb)),fmt,ap);
256 while (isspace(*lbp)) lbp++;
259 lineCurr = (lineCurr ?
260 connectLine(lineCurr,newLineNode(lb)) :
261 (lineHead = newLineNode(lb)));
262 lineCurr->isInline = _G.inLine;
263 lineCurr->isDebug = _G.debugLine;
265 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
268 // fprintf(stderr, "%s\n", lb);
271 void pic16_emitpLabel(int key)
273 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
276 void pic16_emitpLabelFORCE(int key)
278 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+labelOffset));
281 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
285 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
287 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
289 // fprintf(stderr, "%s\n", pcop->name);
292 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
295 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
301 #define pic16_emitcode DEBUGpic16_emitcode
303 /*-----------------------------------------------------------------*/
304 /* pic16_emitcode - writes the code into a file : for now it is simple */
305 /*-----------------------------------------------------------------*/
306 void pic16_emitcode (char *inst,char *fmt, ...)
309 char lb[INITIAL_INLINEASM];
316 sprintf(lb,"%s\t",inst);
318 sprintf(lb,"%s",inst);
319 vsprintf(lb+(strlen(lb)),fmt,ap);
323 while (isspace(*lbp)) lbp++;
326 lineCurr = (lineCurr ?
327 connectLine(lineCurr,newLineNode(lb)) :
328 (lineHead = newLineNode(lb)));
329 lineCurr->isInline = _G.inLine;
330 lineCurr->isDebug = _G.debugLine;
332 // VR fprintf(stderr, "lb = <%s>\n", lbp);
334 // if(pic16_debug_verbose)
335 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
342 /*-----------------------------------------------------------------*/
343 /* pic16_emitDebuggerSymbol - associate the current code location */
344 /* with a debugger symbol */
345 /*-----------------------------------------------------------------*/
347 pic16_emitDebuggerSymbol (char * debugSym)
350 pic16_emitcode (";", "%s ==.", debugSym);
355 /*-----------------------------------------------------------------*/
356 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
357 /*-----------------------------------------------------------------*/
358 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
360 bool r0iu = FALSE , r1iu = FALSE;
361 bool r0ou = FALSE , r1ou = FALSE;
363 //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
365 /* the logic: if r0 & r1 used in the instruction
366 then we are in trouble otherwise */
368 /* first check if r0 & r1 are used by this
369 instruction, in which case we are in trouble */
370 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
371 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
376 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
377 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
379 /* if no usage of r0 then return it */
380 if (!r0iu && !r0ou) {
381 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
382 (*aopp)->type = AOP_R0;
384 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
387 /* if no usage of r1 then return it */
388 if (!r1iu && !r1ou) {
389 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
390 (*aopp)->type = AOP_R1;
392 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
395 /* now we know they both have usage */
396 /* if r0 not used in this instruction */
398 /* push it if not already pushed */
400 //pic16_emitcode ("push","%s",
401 // pic16_regWithIdx(R0_IDX)->dname);
405 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
406 (*aopp)->type = AOP_R0;
408 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
411 /* if r1 not used then */
414 /* push it if not already pushed */
416 //pic16_emitcode ("push","%s",
417 // pic16_regWithIdx(R1_IDX)->dname);
421 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
422 (*aopp)->type = AOP_R1;
423 return pic16_regWithIdx(R1_IDX);
427 /* I said end of world but not quite end of world yet */
428 /* if this is a result then we can push it on the stack*/
430 (*aopp)->type = AOP_STK;
434 /* other wise this is true end of the world */
435 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
436 "getFreePtr should never reach here");
440 /*-----------------------------------------------------------------*/
441 /* newAsmop - creates a new asmOp */
442 /*-----------------------------------------------------------------*/
443 static asmop *newAsmop (short type)
447 aop = Safe_calloc(1,sizeof(asmop));
452 static void genSetDPTR(int n)
456 pic16_emitcode(";", "Select standard DPTR");
457 pic16_emitcode("mov", "dps, #0x00");
461 pic16_emitcode(";", "Select alternate DPTR");
462 pic16_emitcode("mov", "dps, #0x01");
466 /*-----------------------------------------------------------------*/
467 /* resolveIfx - converts an iCode ifx into a form more useful for */
468 /* generating code */
469 /*-----------------------------------------------------------------*/
470 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
473 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
479 resIfx->condition = 1; /* assume that the ifx is true */
480 resIfx->generated = 0; /* indicate that the ifx has not been used */
483 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
486 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
487 __FUNCTION__,__LINE__,resIfx->lbl->key);
492 resIfx->lbl = IC_TRUE(ifx);
494 resIfx->lbl = IC_FALSE(ifx);
495 resIfx->condition = 0;
500 DEBUGpic16_emitcode("; ***","ifx true is non-null");
502 DEBUGpic16_emitcode("; ***","ifx false is non-null");
506 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
510 /*-----------------------------------------------------------------*/
511 /* pointerCode - returns the code for a pointer type */
512 /*-----------------------------------------------------------------*/
513 static int pointerCode (sym_link *etype)
516 return PTR_TYPE(SPEC_OCLS(etype));
521 /*-----------------------------------------------------------------*/
522 /* aopForSym - for a true symbol */
523 /*-----------------------------------------------------------------*/
524 static asmop *aopForSym (iCode *ic, operand *op, bool result)
526 symbol *sym=OP_SYMBOL(op);
528 memmap *space= SPEC_OCLS(sym->etype);
530 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
532 // sym = OP_SYMBOL(op);
534 /* if already has one */
536 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
540 /* if symbol was initially placed onStack then we must re-place it
541 * to direct memory, since pic16 does not have a specific stack */
544 SPEC_OCLS( sym->etype ) = data;
550 /* assign depending on the storage class */
551 /* if it is on the stack or indirectly addressable */
552 /* space we need to assign either r0 or r1 to it */
553 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
555 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
556 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
558 sym->aop = aop = newAsmop(0);
559 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
560 aop->size = getSize(sym->type);
562 /* now assign the address of the variable to
563 the pointer register */
564 if (aop->type != AOP_STK) {
568 pic16_emitcode("push","acc");
570 pic16_emitcode("mov","a,_bp");
571 pic16_emitcode("add","a,#0x%02x",
573 ((char)(sym->stack - _G.nRegsSaved )) :
574 ((char)sym->stack)) & 0xff);
575 pic16_emitcode("mov","%s,a",
576 aop->aopu.aop_ptr->name);
579 pic16_emitcode("pop","acc");
581 pic16_emitcode("mov","%s,#%s",
582 aop->aopu.aop_ptr->name,
584 aop->paged = space->paged;
586 aop->aopu.aop_stk = sym->stack;
591 if (sym->onStack && options.stack10bit)
593 /* It's on the 10 bit stack, which is located in
597 //DEBUGpic16_emitcode(";","%d",__LINE__);
600 pic16_emitcode("push","acc");
602 pic16_emitcode("mov","a,_bp");
603 pic16_emitcode("add","a,#0x%02x",
605 ((char)(sym->stack - _G.nRegsSaved )) :
606 ((char)sym->stack)) & 0xff);
609 pic16_emitcode ("mov","dpx1,#0x40");
610 pic16_emitcode ("mov","dph1,#0x00");
611 pic16_emitcode ("mov","dpl1, a");
615 pic16_emitcode("pop","acc");
617 sym->aop = aop = newAsmop(AOP_DPTR2);
618 aop->size = getSize(sym->type);
622 //DEBUGpic16_emitcode(";","%d",__LINE__);
623 /* if in bit space */
624 if (IN_BITSPACE(space)) {
625 sym->aop = aop = newAsmop (AOP_CRY);
626 aop->aopu.aop_dir = sym->rname ;
627 aop->size = getSize(sym->type);
628 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
631 /* if it is in direct space */
632 if (IN_DIRSPACE(space)) {
633 sym->aop = aop = newAsmop (AOP_DIR);
634 aop->aopu.aop_dir = sym->rname ;
635 aop->size = getSize(sym->type);
636 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
637 pic16_allocDirReg( IC_LEFT(ic) );
642 /* special case for a function */
643 if (IS_FUNC(sym->type)) {
644 sym->aop = aop = newAsmop(AOP_IMMD);
645 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
646 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
647 strcpy(aop->aopu.aop_immd,sym->rname);
648 aop->size = FPTRSIZE;
649 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
655 /* only remaining is far space */
656 /* in which case DPTR gets the address */
657 sym->aop = aop = newAsmop(AOP_PCODE);
659 /* change the next if to 1 to revert to good old immediate code */
660 if(IN_CODESPACE(space)) {
661 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
662 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
663 PCOI(aop->aopu.pcop)->index = 0;
665 /* try to allocate via direct register */
666 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
667 // aop->size = getSize( sym->type );
670 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
671 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
674 if(!pic16_allocDirReg (IC_LEFT(ic)))
678 if(IN_DIRSPACE( space ))
680 else if(IN_CODESPACE( space ))
681 aop->size = FPTRSIZE;
682 else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
683 else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
688 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
690 /* if it is in code space */
691 if (IN_CODESPACE(space))
697 /*-----------------------------------------------------------------*/
698 /* aopForRemat - rematerialzes an object */
699 /*-----------------------------------------------------------------*/
700 static asmop *aopForRemat (operand *op) // x symbol *sym)
702 symbol *sym = OP_SYMBOL(op);
703 iCode *ic = NULL, *oldic;
704 asmop *aop = newAsmop(AOP_PCODE);
710 ic = sym->rematiCode;
712 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
714 if(IS_OP_POINTER(op)) {
715 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
721 // pic16_emitpcomment("ic: %s\n", printILine(ic));
724 val += (int) operandLitValue(IC_RIGHT(ic));
725 } else if (ic->op == '-') {
726 val -= (int) operandLitValue(IC_RIGHT(ic));
730 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
733 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
735 if(!op->isaddr)viaimmd++; else viaimmd=0;
737 /* set the following if to 1 to revert to good old immediate code */
738 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
741 DEBUGpic16_emitcode("%s:%d immediate", __FILE__, __LINE__);
743 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
746 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
748 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
751 PCOI(aop->aopu.pcop)->index = val;
753 DEBUGpic16_emitcode("%s:%d dir", __FILE__, __LINE__);
755 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
756 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
757 // aop->size = AOP_SIZE( IC_LEFT(ic) );
761 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
762 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
764 val, IS_PTR_CONST(operandType(op)));
766 val, IS_CODEPTR(operandType(op)));
769 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
771 pic16_allocDirReg (IC_LEFT(ic));
773 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
779 static int aopIdx (asmop *aop, int offset)
784 if(aop->type != AOP_REG)
787 return aop->aopu.aop_reg[offset]->rIdx;
790 /*-----------------------------------------------------------------*/
791 /* regsInCommon - two operands have some registers in common */
792 /*-----------------------------------------------------------------*/
793 static bool regsInCommon (operand *op1, operand *op2)
798 /* if they have registers in common */
799 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
802 sym1 = OP_SYMBOL(op1);
803 sym2 = OP_SYMBOL(op2);
805 if (sym1->nRegs == 0 || sym2->nRegs == 0)
808 for (i = 0 ; i < sym1->nRegs ; i++) {
813 for (j = 0 ; j < sym2->nRegs ;j++ ) {
817 if (sym2->regs[j] == sym1->regs[i])
825 /*-----------------------------------------------------------------*/
826 /* operandsEqu - equivalent */
827 /*-----------------------------------------------------------------*/
828 static bool operandsEqu ( operand *op1, operand *op2)
832 /* if they not symbols */
833 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
836 sym1 = OP_SYMBOL(op1);
837 sym2 = OP_SYMBOL(op2);
839 /* if both are itemps & one is spilt
840 and the other is not then false */
841 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
842 sym1->isspilt != sym2->isspilt )
845 /* if they are the same */
849 if (sym1->rname[0] && sym2->rname[0]
850 && strcmp (sym1->rname, sym2->rname) == 0)
854 /* if left is a tmp & right is not */
858 (sym1->usl.spillLoc == sym2))
865 (sym2->usl.spillLoc == sym1))
871 /*-----------------------------------------------------------------*/
872 /* pic16_sameRegs - two asmops have the same registers */
873 /*-----------------------------------------------------------------*/
874 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
881 if (aop1->type != AOP_REG ||
882 aop2->type != AOP_REG )
885 if (aop1->size != aop2->size )
888 for (i = 0 ; i < aop1->size ; i++ )
889 if (aop1->aopu.aop_reg[i] !=
890 aop2->aopu.aop_reg[i] )
896 /*-----------------------------------------------------------------*/
897 /* pic16_aopOp - allocates an asmop for an operand : */
898 /*-----------------------------------------------------------------*/
899 void pic16_aopOp (operand *op, iCode *ic, bool result)
908 // DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
910 /* if this a literal */
911 if (IS_OP_LITERAL(op)) {
912 op->aop = aop = newAsmop(AOP_LIT);
913 aop->aopu.aop_lit = op->operand.valOperand;
914 aop->size = getSize(operandType(op));
919 sym_link *type = operandType(op);
921 if(IS_PTR_CONST(type))
925 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
928 /* if already has a asmop then continue */
932 /* if the underlying symbol has a aop */
933 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
934 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
935 op->aop = OP_SYMBOL(op)->aop;
939 /* if this is a true symbol */
940 if (IS_TRUE_SYMOP(op)) {
941 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
942 op->aop = aopForSym(ic, op, result);
946 /* this is a temporary : this has
952 e) can be a return use only */
956 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
957 /* if the type is a conditional */
958 if (sym->regType == REG_CND) {
959 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
964 /* if it is spilt then two situations
966 b) has a spill location */
967 if (sym->isspilt || sym->nRegs == 0) {
969 DEBUGpic16_emitcode(";","%d",__LINE__);
970 /* rematerialize it NOW */
973 sym->aop = op->aop = aop =
975 aop->size = getSize(sym->type);
976 //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
983 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
984 aop->size = getSize(sym->type);
985 for ( i = 0 ; i < 1 ; i++ ) {
986 aop->aopu.aop_str[i] = accUse[i];
987 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
989 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
990 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
998 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
999 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1000 //pic16_allocDirReg (IC_LEFT(ic));
1001 aop->size = getSize(sym->type);
1006 aop = op->aop = sym->aop = newAsmop(AOP_STR);
1007 aop->size = getSize(sym->type);
1008 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1009 aop->aopu.aop_str[i] = fReturn[i];
1011 DEBUGpic16_emitcode(";","%d",__LINE__);
1015 /* else spill location */
1016 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1017 /* force a new aop if sizes differ */
1018 sym->usl.spillLoc->aop = NULL;
1020 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1021 __FUNCTION__,__LINE__,
1022 sym->usl.spillLoc->rname,
1023 sym->rname, sym->usl.spillLoc->offset);
1025 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1026 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1027 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1029 sym->usl.spillLoc->offset, op);
1030 aop->size = getSize(sym->type);
1036 sym_link *type = operandType(op);
1038 if(IS_PTR_CONST(type))
1040 if(IS_CODEPTR(type))
1042 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1045 /* must be in a register */
1046 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1047 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1048 aop->size = sym->nRegs;
1049 for ( i = 0 ; i < sym->nRegs ;i++)
1050 aop->aopu.aop_reg[i] = sym->regs[i];
1053 /*-----------------------------------------------------------------*/
1054 /* pic16_freeAsmop - free up the asmop given to an operand */
1055 /*----------------------------------------------------------------*/
1056 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1073 /* depending on the asmop type only three cases need work AOP_RO
1074 , AOP_R1 && AOP_STK */
1076 switch (aop->type) {
1080 pic16_emitcode ("pop","ar0");
1084 bitVectUnSetBit(ic->rUsed,R0_IDX);
1090 pic16_emitcode ("pop","ar1");
1094 bitVectUnSetBit(ic->rUsed,R1_IDX);
1100 int stk = aop->aopu.aop_stk + aop->size;
1101 bitVectUnSetBit(ic->rUsed,R0_IDX);
1102 bitVectUnSetBit(ic->rUsed,R1_IDX);
1104 getFreePtr(ic,&aop,FALSE);
1106 if (options.stack10bit)
1108 /* I'm not sure what to do here yet... */
1111 "*** Warning: probably generating bad code for "
1112 "10 bit stack mode.\n");
1116 pic16_emitcode ("mov","a,_bp");
1117 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1118 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1120 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1124 pic16_emitcode("pop","acc");
1125 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1127 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1130 pic16_freeAsmop(op,NULL,ic,TRUE);
1132 pic16_emitcode("pop","ar0");
1137 pic16_emitcode("pop","ar1");
1145 /* all other cases just dealloc */
1149 OP_SYMBOL(op)->aop = NULL;
1150 /* if the symbol has a spill */
1152 SPIL_LOC(op)->aop = NULL;
1157 /*-----------------------------------------------------------------*/
1158 /* pic16_aopGet - for fetching value of the aop */
1159 /*-----------------------------------------------------------------*/
1160 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1165 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1167 /* offset is greater than size then zero */
1168 if (offset > (aop->size - 1) &&
1169 aop->type != AOP_LIT)
1172 /* depending on type */
1173 switch (aop->type) {
1177 DEBUGpic16_emitcode(";","%d",__LINE__);
1178 /* if we need to increment it */
1179 while (offset > aop->coff) {
1180 pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1184 while (offset < aop->coff) {
1185 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1189 aop->coff = offset ;
1191 pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1192 return (dname ? "acc" : "a");
1194 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1195 rs = Safe_calloc(1,strlen(s)+1);
1201 DEBUGpic16_emitcode(";","%d",__LINE__);
1202 if (aop->type == AOP_DPTR2)
1207 while (offset > aop->coff) {
1208 pic16_emitcode ("inc","dptr");
1212 while (offset < aop->coff) {
1213 pic16_emitcode("lcall","__decdptr");
1219 pic16_emitcode("clr","a");
1220 pic16_emitcode("movc","a,@a+dptr");
1223 pic16_emitcode("movx","a,@dptr");
1226 if (aop->type == AOP_DPTR2)
1231 return (dname ? "acc" : "a");
1236 sprintf (s,"%s",aop->aopu.aop_immd);
1239 sprintf(s,"(%s >> %d)",
1244 aop->aopu.aop_immd);
1245 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1246 rs = Safe_calloc(1,strlen(s)+1);
1252 sprintf(s,"(%s + %d)",
1255 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1257 sprintf(s,"%s",aop->aopu.aop_dir);
1258 rs = Safe_calloc(1,strlen(s)+1);
1264 // return aop->aopu.aop_reg[offset]->dname;
1266 return aop->aopu.aop_reg[offset]->name;
1269 //pic16_emitcode(";","%d",__LINE__);
1270 return aop->aopu.aop_dir;
1273 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1274 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1276 return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1279 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1280 rs = Safe_calloc(1,strlen(s)+1);
1285 aop->coff = offset ;
1286 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1289 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1291 return aop->aopu.aop_str[offset];
1295 pCodeOp *pcop = aop->aopu.pcop;
1296 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1298 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1299 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1300 sprintf(s,"%s", pcop->name);
1302 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1305 rs = Safe_calloc(1,strlen(s)+1);
1311 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1312 "aopget got unsupported aop->type");
1317 /*-----------------------------------------------------------------*/
1318 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1319 /*-----------------------------------------------------------------*/
1320 pCodeOp *pic16_popGetTempReg(void)
1325 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1330 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1331 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1332 PCOR(pcop)->r->wasUsed=1;
1333 PCOR(pcop)->r->isFree=0;
1335 /* push value on stack */
1336 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1344 /*-----------------------------------------------------------------*/
1345 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1346 /*-----------------------------------------------------------------*/
1347 void pic16_popReleaseTempReg(pCodeOp *pcop)
1349 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1351 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1352 PCOR(pcop)->r->isFree = 1;
1354 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1357 /*-----------------------------------------------------------------*/
1358 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1359 /*-----------------------------------------------------------------*/
1360 pCodeOp *pic16_popGetLabel(unsigned int key)
1363 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1368 return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1371 /*-----------------------------------------------------------------*/
1372 /* pic16_popCopyReg - copy a pcode operator */
1373 /*-----------------------------------------------------------------*/
1374 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1378 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1379 pcor->pcop.type = pc->pcop.type;
1381 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1382 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1384 pcor->pcop.name = NULL;
1387 pcor->rIdx = pc->rIdx;
1390 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1395 /*-----------------------------------------------------------------*/
1396 /* pic16_popGetLit - asm operator to pcode operator conversion */
1397 /*-----------------------------------------------------------------*/
1398 pCodeOp *pic16_popGetLit(unsigned int lit)
1400 return pic16_newpCodeOpLit(lit);
1403 /*-----------------------------------------------------------------*/
1404 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1405 /*-----------------------------------------------------------------*/
1406 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1408 return pic16_newpCodeOpLit2(lit, arg2);
1412 /*-----------------------------------------------------------------*/
1413 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1414 /*-----------------------------------------------------------------*/
1415 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1417 return pic16_newpCodeOpImmd(name, offset,index, 0);
1421 /*-----------------------------------------------------------------*/
1422 /* pic16_popGet - asm operator to pcode operator conversion */
1423 /*-----------------------------------------------------------------*/
1424 pCodeOp *pic16_popGetWithString(char *str)
1430 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1434 pcop = pic16_newpCodeOp(str,PO_STR);
1439 /*-----------------------------------------------------------------*/
1440 /* pic16_popRegFromString - */
1441 /*-----------------------------------------------------------------*/
1442 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1445 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1446 pcop->type = PO_DIR;
1448 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1449 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1454 pcop->name = Safe_calloc(1,strlen(str)+1);
1455 strcpy(pcop->name,str);
1457 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1459 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1460 if(PCOR(pcop)->r == NULL) {
1461 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1462 // __FUNCTION__, __LINE__, str, size, offset);
1463 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1465 //fprintf(stderr, "allocating new register -> %s\n", str);
1467 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1469 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d",__LINE__,pcop->name,size,offset);
1471 PCOR(pcop)->instance = offset;
1476 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1480 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1482 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1483 PCOR(pcop)->rIdx = rIdx;
1484 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1485 PCOR(pcop)->r->isFree = 0;
1486 PCOR(pcop)->r->wasUsed = 1;
1488 pcop->type = PCOR(pcop)->r->pc_type;
1493 /*---------------------------------------------------------------------------------*/
1494 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1496 /*---------------------------------------------------------------------------------*/
1497 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1502 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1504 /* comment the following check, so errors to throw up */
1505 // if(!pcop2)return NULL;
1507 temp = pic16_popGet(aop_dst, offset);
1508 pcop2->pcop2 = temp;
1515 /*--------------------------------------------------------------------------------.-*/
1516 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1517 /* VR 030601 , adapted by Hans Dorn */
1518 /*--------------------------------------------------------------------------------.-*/
1519 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1523 pcop2 = (pCodeOpReg2 *)src;
1531 /*---------------------------------------------------------------------------------*/
1532 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1533 /* movff instruction */
1534 /*---------------------------------------------------------------------------------*/
1535 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1540 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1541 pcop2->pcop2 = pic16_popCopyReg(dst);
1543 /* the pCodeOp may be already allocated */
1544 pcop2 = (pCodeOpReg2 *)(src);
1545 pcop2->pcop2 = (pCodeOp *)(dst);
1552 /*-----------------------------------------------------------------*/
1553 /* pic16_popGet - asm operator to pcode operator conversion */
1554 /*-----------------------------------------------------------------*/
1555 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1557 //char *s = buffer ;
1561 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1562 /* offset is greater than
1565 // if (offset > (aop->size - 1) &&
1566 // aop->type != AOP_LIT)
1567 // return NULL; //zero;
1569 /* depending on type */
1570 switch (aop->type) {
1576 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1577 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1584 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1585 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1589 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1591 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1593 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1595 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1596 PCOR(pcop)->rIdx = rIdx;
1597 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1598 PCOR(pcop)->r->wasUsed=1;
1599 PCOR(pcop)->r->isFree=0;
1601 PCOR(pcop)->instance = offset;
1602 pcop->type = PCOR(pcop)->r->pc_type;
1603 // rs = aop->aopu.aop_reg[offset]->name;
1604 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1608 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1609 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1615 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1616 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1620 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1622 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1624 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1625 PCOR(pcop)->rIdx = rIdx;
1626 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1627 PCOR(pcop)->r->wasUsed=1;
1628 PCOR(pcop)->r->isFree=0;
1630 PCOR(pcop)->instance = offset;
1631 pcop->type = PCOR(pcop)->r->pc_type;
1632 rs = aop->aopu.aop_reg[offset]->name;
1633 DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1638 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1640 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1641 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1642 //if(PCOR(pcop)->r == NULL)
1643 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1647 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1648 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1651 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1652 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1655 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1656 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1657 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1658 pcop->type = PCOR(pcop)->r->pc_type;
1659 pcop->name = PCOR(pcop)->r->name;
1665 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1667 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1668 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1670 switch( aop->aopu.pcop->type ) {
1671 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1672 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1674 assert( 0 ); /* should never reach here */;
1677 PCOI(pcop)->offset = offset;
1682 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1683 "pic16_popGet got unsupported aop->type");
1686 /*-----------------------------------------------------------------*/
1687 /* pic16_aopPut - puts a string for a aop */
1688 /*-----------------------------------------------------------------*/
1689 void pic16_aopPut (asmop *aop, char *s, int offset)
1694 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1696 if (aop->size && offset > ( aop->size - 1)) {
1697 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1698 "pic16_aopPut got offset > aop->size");
1702 /* will assign value to value */
1703 /* depending on where it is ofcourse */
1704 switch (aop->type) {
1707 sprintf(d,"(%s + %d)",
1708 aop->aopu.aop_dir,offset);
1709 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1712 sprintf(d,"%s",aop->aopu.aop_dir);
1715 DEBUGpic16_emitcode(";","%d",__LINE__);
1717 pic16_emitcode("movf","%s,w",s);
1718 pic16_emitcode("movwf","%s",d);
1721 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1722 if(offset >= aop->size) {
1723 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1726 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1729 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1736 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1737 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1740 strcmp(s,"r0") == 0 ||
1741 strcmp(s,"r1") == 0 ||
1742 strcmp(s,"r2") == 0 ||
1743 strcmp(s,"r3") == 0 ||
1744 strcmp(s,"r4") == 0 ||
1745 strcmp(s,"r5") == 0 ||
1746 strcmp(s,"r6") == 0 ||
1747 strcmp(s,"r7") == 0 )
1748 pic16_emitcode("mov","%s,%s ; %d",
1749 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1753 if(strcmp(s,"W")==0 )
1754 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
1756 pic16_emitcode("movwf","%s",
1757 aop->aopu.aop_reg[offset]->name);
1759 if(strcmp(s,zero)==0) {
1760 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1762 } else if(strcmp(s,"W")==0) {
1763 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1764 pcop->type = PO_GPR_REGISTER;
1766 PCOR(pcop)->rIdx = -1;
1767 PCOR(pcop)->r = NULL;
1769 DEBUGpic16_emitcode(";","%d",__LINE__);
1770 pcop->name = Safe_strdup(s);
1771 pic16_emitpcode(POC_MOVFW,pcop);
1772 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1773 } else if(strcmp(s,one)==0) {
1774 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1775 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1777 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1785 if (aop->type == AOP_DPTR2)
1791 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1792 "pic16_aopPut writting to code space");
1796 while (offset > aop->coff) {
1798 pic16_emitcode ("inc","dptr");
1801 while (offset < aop->coff) {
1803 pic16_emitcode("lcall","__decdptr");
1808 /* if not in accumulater */
1811 pic16_emitcode ("movx","@dptr,a");
1813 if (aop->type == AOP_DPTR2)
1821 while (offset > aop->coff) {
1823 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1825 while (offset < aop->coff) {
1827 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1833 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1838 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1840 if (strcmp(s,"r0") == 0 ||
1841 strcmp(s,"r1") == 0 ||
1842 strcmp(s,"r2") == 0 ||
1843 strcmp(s,"r3") == 0 ||
1844 strcmp(s,"r4") == 0 ||
1845 strcmp(s,"r5") == 0 ||
1846 strcmp(s,"r6") == 0 ||
1847 strcmp(s,"r7") == 0 ) {
1849 sprintf(buffer,"a%s",s);
1850 pic16_emitcode("mov","@%s,%s",
1851 aop->aopu.aop_ptr->name,buffer);
1853 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1858 if (strcmp(s,"a") == 0)
1859 pic16_emitcode("push","acc");
1861 pic16_emitcode("push","%s",s);
1866 /* if bit variable */
1867 if (!aop->aopu.aop_dir) {
1868 pic16_emitcode("clr","a");
1869 pic16_emitcode("rlc","a");
1872 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1875 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1878 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1880 lbl = newiTempLabel(NULL);
1882 if (strcmp(s,"a")) {
1885 pic16_emitcode("clr","c");
1886 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1887 pic16_emitcode("cpl","c");
1888 pic16_emitcode("","%05d_DS_:",lbl->key+100);
1889 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1896 if (strcmp(aop->aopu.aop_str[offset],s))
1897 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1902 if (!offset && (strcmp(s,"acc") == 0))
1905 if (strcmp(aop->aopu.aop_str[offset],s))
1906 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1910 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1911 "pic16_aopPut got unsupported aop->type");
1917 /*-----------------------------------------------------------------*/
1918 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1919 /*-----------------------------------------------------------------*/
1920 static void mov2w (asmop *aop, int offset)
1926 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1929 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1931 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1936 /* push pcop into stack */
1937 void pic16_pushpCodeOp(pCodeOp *pcop)
1939 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1940 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1943 /* pop pcop from stack */
1944 void pic16_poppCodeOp(pCodeOp *pcop)
1946 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1950 /*-----------------------------------------------------------------*/
1951 /* pushw - pushes wreg to stack */
1952 /*-----------------------------------------------------------------*/
1955 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1956 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1960 /*-----------------------------------------------------------------*/
1961 /* pushaop - pushes aop to stack */
1962 /*-----------------------------------------------------------------*/
1963 void pushaop(asmop *aop, int offset)
1965 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1966 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1969 /*-----------------------------------------------------------------*/
1970 /* popaop - pops aop from stack */
1971 /*-----------------------------------------------------------------*/
1972 void popaop(asmop *aop, int offset)
1974 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
1975 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1978 void popaopidx(asmop *aop, int offset, int index)
1982 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1984 if(STACK_MODEL_LARGE)ofs++;
1986 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1987 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1990 /*-----------------------------------------------------------------*/
1991 /* reAdjustPreg - points a register back to where it should */
1992 /*-----------------------------------------------------------------*/
1993 static void reAdjustPreg (asmop *aop)
1997 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1999 if ((size = aop->size) <= 1)
2002 switch (aop->type) {
2006 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2010 if (aop->type == AOP_DPTR2)
2016 pic16_emitcode("lcall","__decdptr");
2019 if (aop->type == AOP_DPTR2)
2031 /*-----------------------------------------------------------------*/
2032 /* opIsGptr: returns non-zero if the passed operand is */
2033 /* a generic pointer type. */
2034 /*-----------------------------------------------------------------*/
2035 static int opIsGptr(operand *op)
2037 sym_link *type = operandType(op);
2039 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2040 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2048 /*-----------------------------------------------------------------*/
2049 /* pic16_getDataSize - get the operand data size */
2050 /*-----------------------------------------------------------------*/
2051 int pic16_getDataSize(operand *op)
2053 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2056 return AOP_SIZE(op);
2058 // tsd- in the pic port, the genptr size is 1, so this code here
2059 // fails. ( in the 8051 port, the size was 4).
2062 size = AOP_SIZE(op);
2063 if (size == GPTRSIZE)
2065 sym_link *type = operandType(op);
2066 if (IS_GENPTR(type))
2068 /* generic pointer; arithmetic operations
2069 * should ignore the high byte (pointer type).
2072 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2079 /*-----------------------------------------------------------------*/
2080 /* pic16_outAcc - output Acc */
2081 /*-----------------------------------------------------------------*/
2082 void pic16_outAcc(operand *result)
2085 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2086 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2089 size = pic16_getDataSize(result);
2091 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2094 /* unsigned or positive */
2096 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2101 /*-----------------------------------------------------------------*/
2102 /* pic16_outBitC - output a bit C */
2103 /* Move to result the value of Carry flag -- VR */
2104 /*-----------------------------------------------------------------*/
2105 void pic16_outBitC(operand *result)
2109 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2110 /* if the result is bit */
2111 if (AOP_TYPE(result) == AOP_CRY) {
2112 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2113 pic16_aopPut(AOP(result),"c",0);
2116 i = AOP_SIZE(result);
2118 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2120 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2123 pic16_emitcode("clr","a ; %d", __LINE__);
2124 pic16_emitcode("rlc","a");
2125 pic16_outAcc(result);
2130 /*-----------------------------------------------------------------*/
2131 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2132 /*-----------------------------------------------------------------*/
2133 void pic16_toBoolean(operand *oper)
2135 int size = AOP_SIZE(oper) - 1;
2138 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2140 if ( AOP_TYPE(oper) != AOP_ACC) {
2141 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2144 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2149 #if !defined(GEN_Not)
2150 /*-----------------------------------------------------------------*/
2151 /* genNot - generate code for ! operation */
2152 /*-----------------------------------------------------------------*/
2153 static void pic16_genNot (iCode *ic)
2158 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2159 /* assign asmOps to operand & result */
2160 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2161 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2163 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2164 /* if in bit space then a special case */
2165 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2166 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2167 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2168 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2170 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2171 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2172 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2177 size = AOP_SIZE(IC_LEFT(ic));
2179 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2180 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2181 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2184 pic16_toBoolean(IC_LEFT(ic));
2186 tlbl = newiTempLabel(NULL);
2187 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2188 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2189 pic16_outBitC(IC_RESULT(ic));
2192 /* release the aops */
2193 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2194 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2199 #if !defined(GEN_Cpl)
2200 /*-----------------------------------------------------------------*/
2201 /* genCpl - generate code for complement */
2202 /*-----------------------------------------------------------------*/
2203 static void pic16_genCpl (iCode *ic)
2209 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2210 /* assign asmOps to operand & result */
2211 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2212 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2214 /* if both are in bit space then
2216 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2217 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2219 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2220 pic16_emitcode("cpl","c");
2221 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2225 size = AOP_SIZE(IC_RESULT(ic));
2228 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2230 pic16_emitcode("cpl","a");
2231 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2233 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2234 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2236 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2237 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2245 /* release the aops */
2246 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2247 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2251 /*-----------------------------------------------------------------*/
2252 /* genUminusFloat - unary minus for floating points */
2253 /*-----------------------------------------------------------------*/
2254 static void genUminusFloat(operand *op,operand *result)
2256 int size ,offset =0 ;
2259 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2260 /* for this we just need to flip the
2261 first it then copy the rest in place */
2262 size = AOP_SIZE(op) - 1;
2263 l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2267 pic16_emitcode("cpl","acc.7");
2268 pic16_aopPut(AOP(result),"a",3);
2271 pic16_aopPut(AOP(result),
2272 pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2278 /*-----------------------------------------------------------------*/
2279 /* genUminus - unary minus code generation */
2280 /*-----------------------------------------------------------------*/
2281 static void genUminus (iCode *ic)
2284 sym_link *optype, *rtype;
2286 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2289 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2290 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2292 /* if both in bit space then special case */
2293 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2294 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2296 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2297 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2298 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2303 optype = operandType(IC_LEFT(ic));
2304 rtype = operandType(IC_RESULT(ic));
2306 /* if float then do float stuff */
2307 if (IS_FLOAT(optype)) {
2308 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2312 /* otherwise subtract from zero by taking the 2's complement */
2313 size = AOP_SIZE(IC_LEFT(ic));
2315 for(i=0; i<size; i++) {
2316 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2317 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)),i));
2319 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2320 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2324 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2325 for(i=1; i<size; i++) {
2327 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2331 /* release the aops */
2332 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2333 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2336 /*-----------------------------------------------------------------*/
2337 /* saveRegisters - will look for a call and save the registers */
2338 /*-----------------------------------------------------------------*/
2339 static void saveRegisters(iCode *lic)
2346 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2348 for (ic = lic ; ic ; ic = ic->next)
2349 if (ic->op == CALL || ic->op == PCALL)
2353 fprintf(stderr,"found parameter push with no function call\n");
2357 /* if the registers have been saved already then
2359 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2362 /* find the registers in use at this time
2363 and push them away to safety */
2364 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2368 if (options.useXstack) {
2369 if (bitVectBitValue(rsave,R0_IDX))
2370 pic16_emitcode("mov","b,r0");
2371 pic16_emitcode("mov","r0,%s",spname);
2372 for (i = 0 ; i < pic16_nRegs ; i++) {
2373 if (bitVectBitValue(rsave,i)) {
2375 pic16_emitcode("mov","a,b");
2377 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2378 pic16_emitcode("movx","@r0,a");
2379 pic16_emitcode("inc","r0");
2382 pic16_emitcode("mov","%s,r0",spname);
2383 if (bitVectBitValue(rsave,R0_IDX))
2384 pic16_emitcode("mov","r0,b");
2386 //for (i = 0 ; i < pic16_nRegs ; i++) {
2387 // if (bitVectBitValue(rsave,i))
2388 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2391 dtype = operandType(IC_LEFT(ic));
2392 if (currFunc && dtype &&
2393 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2394 IFFUNC_ISISR(currFunc->type) &&
2397 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2400 /*-----------------------------------------------------------------*/
2401 /* unsaveRegisters - pop the pushed registers */
2402 /*-----------------------------------------------------------------*/
2403 static void unsaveRegisters (iCode *ic)
2408 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2409 /* find the registers in use at this time
2410 and push them away to safety */
2411 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2414 if (options.useXstack) {
2415 pic16_emitcode("mov","r0,%s",spname);
2416 for (i = pic16_nRegs ; i >= 0 ; i--) {
2417 if (bitVectBitValue(rsave,i)) {
2418 pic16_emitcode("dec","r0");
2419 pic16_emitcode("movx","a,@r0");
2421 pic16_emitcode("mov","b,a");
2423 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2427 pic16_emitcode("mov","%s,r0",spname);
2428 if (bitVectBitValue(rsave,R0_IDX))
2429 pic16_emitcode("mov","r0,b");
2431 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2432 // if (bitVectBitValue(rsave,i))
2433 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2439 /*-----------------------------------------------------------------*/
2441 /*-----------------------------------------------------------------*/
2442 static void pushSide(operand * oper, int size)
2445 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2447 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2448 if (AOP_TYPE(oper) != AOP_REG &&
2449 AOP_TYPE(oper) != AOP_DIR &&
2451 pic16_emitcode("mov","a,%s",l);
2452 pic16_emitcode("push","acc");
2454 pic16_emitcode("push","%s",l);
2459 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2461 // (AOP(left)->aopu.pcop->type == PO_DIR)?
2463 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2464 pic16_emitpcode(POC_MOVFW, src);
2465 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2467 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2468 src, pic16_popGet(AOP(op), offset)));
2473 /*-----------------------------------------------------------------*/
2474 /* assignResultValue - assign results to oper, rescall==1 is */
2475 /* called from genCall() or genPCall() */
2476 /*-----------------------------------------------------------------*/
2477 static void assignResultValue(operand * oper, int rescall)
2479 int size = AOP_SIZE(oper);
2481 DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2482 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2485 /* assign result from a call/pcall function() */
2487 /* function results are stored in a special order,
2488 * see top of file with Function return policy, or manual */
2491 /* 8-bits, result in WREG */
2492 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2495 /* 16-bits, result in PRODL:WREG */
2496 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2500 /* 24-bits, result in PRODH:PRODL:WREG */
2501 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2505 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2506 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2509 /* >32-bits, result on stack, and FSR0 points to beginning.
2510 * Fix stack when done */
2513 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2514 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2516 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2521 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2522 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2523 if(STACK_MODEL_LARGE) {
2525 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2529 if(!GpsuedoStkPtr) {
2530 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2531 /* The last byte in the assignment is in W */
2533 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2538 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2539 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2541 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2547 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2549 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2559 /*-----------------------------------------------------------------*/
2560 /* genIpush - genrate code for pushing this gets a little complex */
2561 /*-----------------------------------------------------------------*/
2562 static void genIpush (iCode *ic)
2565 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2567 int size, offset = 0 ;
2571 /* if this is not a parm push : ie. it is spill push
2572 and spill push is always done on the local stack */
2573 if (!ic->parmPush) {
2575 /* and the item is spilt then do nothing */
2576 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2579 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2580 size = AOP_SIZE(IC_LEFT(ic));
2581 /* push it on the stack */
2583 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2588 pic16_emitcode("push","%s",l);
2593 /* this is a paramter push: in this case we call
2594 the routine to find the call and save those
2595 registers that need to be saved */
2598 /* then do the push */
2599 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2602 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2603 size = AOP_SIZE(IC_LEFT(ic));
2606 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2607 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2608 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2610 pic16_emitcode("mov","a,%s",l);
2611 pic16_emitcode("push","acc");
2613 pic16_emitcode("push","%s",l);
2616 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2620 /*-----------------------------------------------------------------*/
2621 /* genIpop - recover the registers: can happen only for spilling */
2622 /*-----------------------------------------------------------------*/
2623 static void genIpop (iCode *ic)
2625 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2630 /* if the temp was not pushed then */
2631 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2634 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2635 size = AOP_SIZE(IC_LEFT(ic));
2638 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2641 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2645 /*-----------------------------------------------------------------*/
2646 /* unsaverbank - restores the resgister bank from stack */
2647 /*-----------------------------------------------------------------*/
2648 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2650 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2656 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2658 if (options.useXstack) {
2660 r = getFreePtr(ic,&aop,FALSE);
2663 pic16_emitcode("mov","%s,_spx",r->name);
2664 pic16_emitcode("movx","a,@%s",r->name);
2665 pic16_emitcode("mov","psw,a");
2666 pic16_emitcode("dec","%s",r->name);
2669 pic16_emitcode ("pop","psw");
2672 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2673 if (options.useXstack) {
2674 pic16_emitcode("movx","a,@%s",r->name);
2675 //pic16_emitcode("mov","(%s+%d),a",
2676 // regspic16[i].base,8*bank+regspic16[i].offset);
2677 pic16_emitcode("dec","%s",r->name);
2680 pic16_emitcode("pop",""); //"(%s+%d)",
2681 //regspic16[i].base,8*bank); //+regspic16[i].offset);
2684 if (options.useXstack) {
2686 pic16_emitcode("mov","_spx,%s",r->name);
2687 pic16_freeAsmop(NULL,aop,ic,TRUE);
2693 /*-----------------------------------------------------------------*/
2694 /* saverbank - saves an entire register bank on the stack */
2695 /*-----------------------------------------------------------------*/
2696 static void saverbank (int bank, iCode *ic, bool pushPsw)
2698 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2704 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2705 if (options.useXstack) {
2708 r = getFreePtr(ic,&aop,FALSE);
2709 pic16_emitcode("mov","%s,_spx",r->name);
2713 for (i = 0 ; i < pic16_nRegs ;i++) {
2714 if (options.useXstack) {
2715 pic16_emitcode("inc","%s",r->name);
2716 //pic16_emitcode("mov","a,(%s+%d)",
2717 // regspic16[i].base,8*bank+regspic16[i].offset);
2718 pic16_emitcode("movx","@%s,a",r->name);
2720 pic16_emitcode("push","");// "(%s+%d)",
2721 //regspic16[i].base,8*bank+regspic16[i].offset);
2725 if (options.useXstack) {
2726 pic16_emitcode("mov","a,psw");
2727 pic16_emitcode("movx","@%s,a",r->name);
2728 pic16_emitcode("inc","%s",r->name);
2729 pic16_emitcode("mov","_spx,%s",r->name);
2730 pic16_freeAsmop (NULL,aop,ic,TRUE);
2733 pic16_emitcode("push","psw");
2735 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2743 /*-----------------------------------------------------------------*/
2744 /* genCall - generates a call statement */
2745 /*-----------------------------------------------------------------*/
2746 static void genCall (iCode *ic)
2751 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2753 /* if caller saves & we have not saved then */
2757 /* if we are calling a function that is not using
2758 * the same register bank then we need to save the
2759 * destination registers on the stack */
2760 dtype = operandType(IC_LEFT(ic));
2761 if (currFunc && dtype &&
2762 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2763 IFFUNC_ISISR(currFunc->type) &&
2766 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2768 /* if send set is not empty the assign */
2772 /* For the Pic port, there is no data stack.
2773 * So parameters passed to functions are stored
2774 * in registers. (The pCode optimizer will get
2775 * rid of most of these :). */
2777 int psuedoStkPtr=-1;
2778 int firstTimeThruLoop = 1;
2780 _G.sendSet = reverseSet(_G.sendSet);
2782 /* First figure how many parameters are getting passed */
2783 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2784 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2785 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2786 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2789 stackParms = psuedoStkPtr;
2791 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2792 int size, offset = 0;
2794 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2795 size = AOP_SIZE(IC_LEFT(sic));
2798 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2799 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2800 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2802 if(!firstTimeThruLoop) {
2803 /* If this is not the first time we've been through the loop
2804 * then we need to save the parameter in a temporary
2805 * register. The last byte of the last parameter is
2809 --psuedoStkPtr; // sanity check
2812 firstTimeThruLoop=0;
2814 mov2w (AOP(IC_LEFT(sic)), offset);
2817 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2823 pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2824 OP_SYMBOL(IC_LEFT(ic))->rname :
2825 OP_SYMBOL(IC_LEFT(ic))->name));
2828 /* if we need assign a result value */
2829 if ((IS_ITEMP(IC_RESULT(ic)) &&
2830 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2831 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2832 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2835 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2838 assignResultValue(IC_RESULT(ic), 1);
2840 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2841 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2843 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2847 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2848 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2849 if(STACK_MODEL_LARGE) {
2851 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2855 /* adjust the stack for parameters if required */
2856 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2858 if (ic->parmBytes) {
2861 if (ic->parmBytes > 3) {
2862 pic16_emitcode("mov","a,%s",spname);
2863 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2864 pic16_emitcode("mov","%s,a",spname);
2866 for ( i = 0 ; i < ic->parmBytes ;i++)
2867 pic16_emitcode("dec","%s",spname);
2871 /* if register bank was saved then pop them */
2873 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2875 /* if we hade saved some registers then unsave them */
2876 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2877 unsaveRegisters (ic);
2883 /*-----------------------------------------------------------------*/ // patch 14
2884 /* genPcall - generates a call by pointer statement */
2885 /*-----------------------------------------------------------------*/
2887 // new version, created from genCall
2889 static void genPcall (iCode *ic)
2893 symbol *retlbl = newiTempLabel(NULL);
2894 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2896 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2898 /* if caller saves & we have not saved then */
2902 /* if we are calling a function that is not using
2903 * the same register bank then we need to save the
2904 * destination registers on the stack */
2905 dtype = operandType(IC_LEFT(ic));
2906 if (currFunc && dtype &&
2907 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2908 IFFUNC_ISISR(currFunc->type) &&
2911 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2913 /* if send set is not empty the assign */
2917 /* For the Pic port, there is no data stack.
2918 * So parameters passed to functions are stored
2919 * in registers. (The pCode optimizer will get
2920 * rid of most of these :). */
2922 int psuedoStkPtr=-1;
2923 int firstTimeThruLoop = 1;
2925 _G.sendSet = reverseSet(_G.sendSet);
2927 /* First figure how many parameters are getting passed */
2928 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2929 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2930 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2931 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2934 stackParms = psuedoStkPtr;
2936 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2937 int size, offset = 0;
2939 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2940 size = AOP_SIZE(IC_LEFT(sic));
2943 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2944 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2945 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2947 if(!firstTimeThruLoop) {
2948 /* If this is not the first time we've been through the loop
2949 * then we need to save the parameter in a temporary
2950 * register. The last byte of the last parameter is
2954 --psuedoStkPtr; // sanity check
2957 firstTimeThruLoop=0;
2959 mov2w (AOP(IC_LEFT(sic)), offset);
2962 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2967 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2969 // push return address
2970 // push $ on return stack, then replace with retlbl
2972 pic16_emitpcodeNULLop(POC_PUSH);
2974 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2975 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2976 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2977 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2978 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2979 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2981 /* make the call by writing the pointer into pc */
2982 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
2983 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
2985 // note: MOVFF to PCL not allowed
2986 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
2987 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2990 // pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key));
2991 // pic16_emitpcodeNULLop(POC_NOP);
2992 // pic16_emitpcodeNULLop(POC_NOP);
2994 /* return address is here: (X) */
2995 pic16_emitpLabelFORCE(retlbl->key);
2997 // pic16_emitpcodeNULLop(POC_NOP);
2999 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3002 /* if we need assign a result value */
3003 if ((IS_ITEMP(IC_RESULT(ic)) &&
3004 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3005 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
3006 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3009 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3012 assignResultValue(IC_RESULT(ic), 1);
3014 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3015 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3017 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3021 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3022 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3023 if(STACK_MODEL_LARGE) {
3025 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3029 /* adjust the stack for parameters if required */
3030 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3032 if (ic->parmBytes) {
3035 if (ic->parmBytes > 3) {
3036 pic16_emitcode("mov","a,%s",spname);
3037 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3038 pic16_emitcode("mov","%s,a",spname);
3040 for ( i = 0 ; i < ic->parmBytes ;i++)
3041 pic16_emitcode("dec","%s",spname);
3044 /* if register bank was saved then pop them */
3046 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3048 /* if we hade saved some registers then unsave them */
3049 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3050 unsaveRegisters (ic);
3055 // old version, kept for reference
3057 /*-----------------------------------------------------------------*/
3058 /* genPcall - generates a call by pointer statement */
3059 /*-----------------------------------------------------------------*/
3060 static void genPcall (iCode *ic)
3063 symbol *rlbl = newiTempLabel(NULL);
3066 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3067 /* if caller saves & we have not saved then */
3071 /* if we are calling a function that is not using
3072 the same register bank then we need to save the
3073 destination registers on the stack */
3074 dtype = operandType(IC_LEFT(ic));
3075 if (currFunc && dtype &&
3076 IFFUNC_ISISR(currFunc->type) &&
3077 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3078 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3081 /* push the return address on to the stack */
3082 pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3083 pic16_emitcode("push","acc");
3084 pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3085 pic16_emitcode("push","acc");
3087 if (options.model == MODEL_FLAT24)
3089 pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3090 pic16_emitcode("push","acc");
3093 /* now push the calling address */
3094 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3096 pushSide(IC_LEFT(ic), FPTRSIZE);
3098 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3100 /* if send set is not empty the assign */
3104 for (sic = setFirstItem(_G.sendSet) ; sic ;
3105 sic = setNextItem(_G.sendSet)) {
3106 int size, offset = 0;
3107 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3108 size = AOP_SIZE(IC_LEFT(sic));
3110 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3112 if (strcmp(l,fReturn[offset]))
3113 pic16_emitcode("mov","%s,%s",
3118 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3123 pic16_emitcode("ret","");
3124 pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3127 /* if we need assign a result value */
3128 if ((IS_ITEMP(IC_RESULT(ic)) &&
3129 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3130 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3131 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3134 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3137 assignResultValue(IC_RESULT(ic), 1);
3139 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3142 /* adjust the stack for parameters if
3144 if (ic->parmBytes) {
3146 if (ic->parmBytes > 3) {
3147 pic16_emitcode("mov","a,%s",spname);
3148 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3149 pic16_emitcode("mov","%s,a",spname);
3151 for ( i = 0 ; i < ic->parmBytes ;i++)
3152 pic16_emitcode("dec","%s",spname);
3156 /* if register bank was saved then unsave them */
3157 if (currFunc && dtype &&
3158 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3159 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3161 /* if we hade saved some registers then
3164 unsaveRegisters (ic);
3170 /*-----------------------------------------------------------------*/
3171 /* resultRemat - result is rematerializable */
3172 /*-----------------------------------------------------------------*/
3173 static int resultRemat (iCode *ic)
3175 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3176 if (SKIP_IC(ic) || ic->op == IFX)
3179 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3180 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3181 if (sym->remat && !POINTER_SET(ic))
3188 #if defined(__BORLANDC__) || defined(_MSC_VER)
3189 #define STRCASECMP stricmp
3191 #define STRCASECMP strcasecmp
3195 /*-----------------------------------------------------------------*/
3196 /* inExcludeList - return 1 if the string is in exclude Reg list */
3197 /*-----------------------------------------------------------------*/
3198 static bool inExcludeList(char *s)
3200 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3203 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3204 if (options.excludeRegs[i] &&
3205 STRCASECMP(options.excludeRegs[i],"none") == 0)
3208 for ( i = 0 ; options.excludeRegs[i]; i++) {
3209 if (options.excludeRegs[i] &&
3210 STRCASECMP(s,options.excludeRegs[i]) == 0)
3217 /*-----------------------------------------------------------------*/
3218 /* genFunction - generated code for function entry */
3219 /*-----------------------------------------------------------------*/
3220 static void genFunction (iCode *ic)
3225 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
3227 labelOffset += (max_key+4);
3232 ftype = operandType(IC_LEFT(ic));
3233 sym = OP_SYMBOL(IC_LEFT(ic));
3235 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3236 /* create an absolute section at the interrupt vector:
3237 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3245 sym = OP_SYMBOL( IC_LEFT(ic));
3247 if(interrupts[i]->name
3248 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3255 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3256 __FILE__, __LINE__, sym->name);
3259 _G.interruptvector = found;
3262 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3263 asym = newSymbol(asymname, 0);
3265 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3266 pic16_addpBlock( apb );
3268 pic16_addpCode2pBlock(apb,
3269 pic16_newpCodeCharP(";-----------------------------------------"));
3272 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3274 pic16_addpCode2pBlock(apb,
3275 pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3277 /* mark the end of this tiny function */
3278 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3283 abSym = Safe_calloc(1, sizeof(absSym));
3284 abSym->name = Safe_strdup( asymname );
3286 switch( _G.interruptvector ) {
3287 case 0: abSym->address = 0x000000; break;
3288 case 1: abSym->address = 0x000008; break;
3289 case 2: abSym->address = 0x000018; break;
3293 /* relocate interrupt vectors if needed */
3294 abSym->address += pic16_options.ivt_loc;
3296 addSet(&absSymSet, abSym);
3301 /* create the function header */
3302 pic16_emitcode(";","-----------------------------------------");
3303 pic16_emitcode(";"," function %s",sym->name);
3304 pic16_emitcode(";","-----------------------------------------");
3306 pic16_emitcode("","%s:",sym->rname);
3307 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3313 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3314 if(!strcmp(ab->name, sym->name)) {
3315 pic16_pBlockConvert2Absolute(pb);
3322 if(IFFUNC_ISNAKED(ftype)) {
3323 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3327 /* if critical function then turn interrupts off */
3328 if (IFFUNC_ISCRITICAL(ftype))
3329 pic16_emitcode("clr","ea");
3331 /* if this is an interrupt service routine then
3332 * save acc, b, dpl, dph */
3333 if (IFFUNC_ISISR(sym->type)) {
3335 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3336 if(!(_G.interruptvector == 1)) {
3338 /* do not save WREG,STATUS,BSR for high priority interrupts
3339 * because they are stored in the hardware shadow registers already */
3341 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3342 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3343 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3346 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3347 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3348 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3349 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3351 // pic16_pBlockConvert2ISR(pb);
3353 /* if any registers used */
3354 if (sym->regsUsed) {
3355 /* save the registers used */
3356 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3357 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3358 if (bitVectBitValue(sym->regsUsed,i)) {
3359 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3360 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3361 // pic16_regWithIdx(i)->name);
3363 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3369 /* emit code to setup stack frame if user enabled,
3370 * and function is not main() */
3372 // fprintf(stderr, "function name: %s\n", sym->name);
3373 if(strcmp(sym->name, "main")) {
3374 if(/*!options.ommitFramePtr || */sym->regsUsed) {
3375 /* setup the stack frame */
3376 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3377 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3378 if(STACK_MODEL_LARGE)
3379 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3383 /* if callee-save to be used for this function
3384 * then save the registers being used in this function */
3385 // if (IFFUNC_CALLEESAVES(sym->type))
3389 // fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3391 // pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3393 /* if any registers used */
3394 if (sym->regsUsed) {
3395 /* save the registers used */
3396 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3397 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3398 if (bitVectBitValue(sym->regsUsed,i)) {
3400 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3401 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3402 // pic16_regWithIdx(i)->name);
3404 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3406 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3407 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3408 // &pic16_pc_postdec1, 0));
3420 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3422 if (options.useXstack) {
3423 pic16_emitcode("mov","r0,%s",spname);
3424 pic16_emitcode("mov","a,_bp");
3425 pic16_emitcode("movx","@r0,a");
3426 pic16_emitcode("inc","%s",spname);
3428 /* set up the stack */
3429 pic16_emitcode ("push","_bp"); /* save the callers stack */
3431 pic16_emitcode ("mov","_bp,%s",spname);
3434 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3436 /* adjust the stack for the function */
3441 werror(W_STACK_OVERFLOW,sym->name);
3443 if (i > 3 && sym->recvSize < 4) {
3444 pic16_emitcode ("mov","a,sp");
3445 pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3446 pic16_emitcode ("mov","sp,a");
3449 pic16_emitcode("inc","sp");
3453 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3455 pic16_emitcode ("mov","a,_spx");
3456 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3457 pic16_emitcode ("mov","_spx,a");
3462 /*-----------------------------------------------------------------*/
3463 /* genEndFunction - generates epilogue for functions */
3464 /*-----------------------------------------------------------------*/
3465 static void genEndFunction (iCode *ic)
3467 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3469 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3471 if(IFFUNC_ISNAKED(sym->type)) {
3472 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3477 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3479 pic16_emitcode ("mov","%s,_bp",spname);
3483 /* if use external stack but some variables were
3484 added to the local stack then decrement the
3486 if (options.useXstack && sym->stack) {
3487 pic16_emitcode("mov","a,sp");
3488 pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3489 pic16_emitcode("mov","sp,a");
3494 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3495 if (options.useXstack) {
3496 pic16_emitcode("mov","r0,%s",spname);
3497 pic16_emitcode("movx","a,@r0");
3498 pic16_emitcode("mov","_bp,a");
3499 pic16_emitcode("dec","%s",spname);
3503 pic16_emitcode ("pop","_bp");
3508 if (IFFUNC_ISISR(sym->type)) {
3509 /* now we need to restore the registers */
3510 /* if any registers used */
3511 if (sym->regsUsed) {
3514 /* restore registers used */
3515 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3516 for ( i = sym->regsUsed->size; i >= 0; i--) {
3517 if (bitVectBitValue(sym->regsUsed,i)) {
3519 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3520 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3521 // pic16_regWithIdx(i)->name);
3523 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3525 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3526 // &pic16_pc_preinc1,
3527 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3533 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3534 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3535 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3536 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3538 if(!(_G.interruptvector == 1)) {
3539 /* do not restore interrupt vector for WREG,STATUS,BSR
3540 * for high priority interrupt, see genFunction */
3542 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3543 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3544 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3547 _G.interruptvector = 0; /* sanity check */
3549 // pic16_pBlockConvert2ISR(pb);
3552 /* if debug then send end of function */
3553 /* if (options.debug && currFunc) */
3555 debugFile->writeEndFunction (currFunc, ic, 1);
3558 pic16_emitpcodeNULLop(POC_RETFIE);
3560 if (IFFUNC_ISCRITICAL(sym->type))
3561 pic16_emitcode("setb","ea");
3564 // pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3566 /* if any registers used */
3567 if (sym->regsUsed) {
3569 /* save the registers used */
3570 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3571 for ( i = sym->regsUsed->size; i >= 0; i--) {
3572 if (bitVectBitValue(sym->regsUsed,i)) {
3574 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3575 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3576 // pic16_regWithIdx(i)->name);
3578 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3580 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3581 // &pic16_pc_preinc1,
3582 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3589 pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3590 /* if debug then send end of function */
3592 debugFile->writeEndFunction (currFunc, ic, 1);
3595 /* insert code to restore stack frame, if user enabled it
3596 * and function is not main() */
3599 if(strcmp(sym->name, "main")) {
3600 if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3601 /* restore stack frame */
3602 if(STACK_MODEL_LARGE)
3603 pic16_emitpcode(POC_MOVFF,
3604 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3605 pic16_emitpcode(POC_MOVFF,
3606 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3610 pic16_emitcode ("return","");
3611 pic16_emitpcodeNULLop(POC_RETURN);
3613 /* Mark the end of a function */
3614 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3620 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3624 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3626 if(dest->type != PO_WREG)
3627 pic16_emitpcode(POC_MOVWF, dest);
3629 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3630 pic16_popGet(AOP(op), offset), dest));
3634 /*-----------------------------------------------------------------*/
3635 /* genRet - generate code for return statement */
3636 /*-----------------------------------------------------------------*/
3637 static void genRet (iCode *ic)
3642 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3643 /* if we have no return value then
3644 * just generate the "ret" */
3649 /* we have something to return then
3650 * move the return value into place */
3651 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3652 size = AOP_SIZE(IC_LEFT(ic));
3656 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3657 // pic16_emitpcode(POC_MOVFF,
3658 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3661 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3662 // pic16_emitpcode(POC_MOVFF,
3663 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3666 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3667 // pic16_emitpcode(POC_MOVFF,
3668 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3671 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3673 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3674 // pic16_emitpcode(POC_MOVFF,
3675 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3678 /* >32-bits, setup stack and FSR0 */
3680 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3681 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3683 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3685 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3690 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3691 pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3693 if(STACK_MODEL_LARGE) {
3694 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3695 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3697 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3702 /* old code, left here for reference -- VR */
3706 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3708 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3709 pic16_emitpcomment("push %s",l);
3712 DEBUGpic16_emitcode(";", "%d", __LINE__);
3713 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3714 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3716 if (strcmp(fReturn[offset],l)) {
3717 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3718 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3719 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3721 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3725 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3735 if (strcmp(fReturn[pushed],"a"))
3736 pic16_emitcode("pop",fReturn[pushed]);
3738 pic16_emitcode("pop","acc");
3744 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3747 /* generate a jump to the return label
3748 * if the next is not the return statement */
3749 if (!(ic->next && ic->next->op == LABEL
3750 && IC_LABEL(ic->next) == returnLabel)) {
3752 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3753 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3757 /*-----------------------------------------------------------------*/
3758 /* genLabel - generates a label */
3759 /*-----------------------------------------------------------------*/
3760 static void genLabel (iCode *ic)
3764 /* special case never generate */
3765 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3766 if (IC_LABEL(ic) == entryLabel)
3769 pic16_emitpLabel(IC_LABEL(ic)->key);
3770 pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3773 /*-----------------------------------------------------------------*/
3774 /* genGoto - generates a goto */
3775 /*-----------------------------------------------------------------*/
3777 static void genGoto (iCode *ic)
3779 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3780 pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3784 /*-----------------------------------------------------------------*/
3785 /* genMultbits :- multiplication of bits */
3786 /*-----------------------------------------------------------------*/
3787 static void genMultbits (operand *left,
3791 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3793 if(!pic16_sameRegs(AOP(result),AOP(right)))
3794 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3796 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3797 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3798 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3803 /*-----------------------------------------------------------------*/
3804 /* genMultOneByte : 8 bit multiplication & division */
3805 /*-----------------------------------------------------------------*/
3806 static void genMultOneByte (operand *left,
3811 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3812 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3813 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3815 /* (if two literals, the value is computed before) */
3816 /* if one literal, literal on the right */
3817 if (AOP_TYPE(left) == AOP_LIT){
3823 /* size is already checked in genMult == 1 */
3824 // size = AOP_SIZE(result);
3826 if (AOP_TYPE(right) == AOP_LIT){
3827 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3828 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3829 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3830 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3832 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3833 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3834 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3835 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3838 pic16_genMult8X8_8 (left, right,result);
3841 /*-----------------------------------------------------------------*/
3842 /* genMultOneWord : 16 bit multiplication */
3843 /*-----------------------------------------------------------------*/
3844 static void genMultOneWord (operand *left,
3849 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3850 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3851 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3853 /* (if two literals, the value is computed before)
3854 * if one literal, literal on the right */
3855 if (AOP_TYPE(left) == AOP_LIT){
3861 /* size is checked already == 2 */
3862 // size = AOP_SIZE(result);
3864 if (AOP_TYPE(right) == AOP_LIT) {
3865 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3866 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3867 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3868 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3870 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3871 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3872 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3873 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3876 pic16_genMult16X16_16(left, right,result);
3879 /*-----------------------------------------------------------------*/
3880 /* genMultOneLong : 32 bit multiplication */
3881 /*-----------------------------------------------------------------*/
3882 static void genMultOneLong (operand *left,
3887 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3888 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3889 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3891 /* (if two literals, the value is computed before)
3892 * if one literal, literal on the right */
3893 if (AOP_TYPE(left) == AOP_LIT){
3899 /* size is checked already == 4 */
3900 // size = AOP_SIZE(result);
3902 if (AOP_TYPE(right) == AOP_LIT) {
3903 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3904 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3905 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3906 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3908 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3909 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3910 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3911 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3914 pic16_genMult32X32_32(left, right,result);
3919 /*-----------------------------------------------------------------*/
3920 /* genMult - generates code for multiplication */
3921 /*-----------------------------------------------------------------*/
3922 static void genMult (iCode *ic)
3924 operand *left = IC_LEFT(ic);
3925 operand *right = IC_RIGHT(ic);
3926 operand *result= IC_RESULT(ic);
3928 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3929 /* assign the amsops */
3930 pic16_aopOp (left,ic,FALSE);
3931 pic16_aopOp (right,ic,FALSE);
3932 pic16_aopOp (result,ic,TRUE);
3934 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3936 /* special cases first *
3938 if (AOP_TYPE(left) == AOP_CRY
3939 && AOP_TYPE(right)== AOP_CRY) {
3940 genMultbits(left,right,result);
3944 /* if both are of size == 1 */
3945 if(AOP_SIZE(left) == 1
3946 && AOP_SIZE(right) == 1) {
3947 genMultOneByte(left,right,result);
3951 /* if both are of size == 2 */
3952 if(AOP_SIZE(left) == 2
3953 && AOP_SIZE(right) == 2) {
3954 genMultOneWord(left, right, result);
3958 /* if both are of size == 4 */
3959 if(AOP_SIZE(left) == 4
3960 && AOP_SIZE(right) == 4) {
3961 genMultOneLong(left, right, result);
3965 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3968 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3969 /* should have been converted to function call */
3973 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3974 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3975 pic16_freeAsmop(result,NULL,ic,TRUE);
3978 /*-----------------------------------------------------------------*/
3979 /* genDivbits :- division of bits */
3980 /*-----------------------------------------------------------------*/
3981 static void genDivbits (operand *left,
3988 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3989 /* the result must be bit */
3990 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3991 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3995 pic16_emitcode("div","ab");
3996 pic16_emitcode("rrc","a");
3997 pic16_aopPut(AOP(result),"c",0);
4000 /*-----------------------------------------------------------------*/
4001 /* genDivOneByte : 8 bit division */
4002 /*-----------------------------------------------------------------*/
4003 static void genDivOneByte (operand *left,
4007 sym_link *opetype = operandType(result);
4012 /* result = divident / divisor
4013 * - divident may be a register or a literal,
4014 * - divisor may be a register or a literal,
4015 * so there are 3 cases (literal / literal is optimized
4016 * by the front-end) to handle.
4017 * In addition we must handle signed and unsigned, which
4018 * result in 6 final different cases -- VR */
4020 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4021 size = AOP_SIZE(result) - 1;
4023 /* signed or unsigned */
4024 if (SPEC_USIGN(opetype)) {
4025 pCodeOp *pct1, /* count */
4028 symbol *label1, *label2, *label3;;
4031 /* unsigned is easy */
4033 pct1 = pic16_popGetTempReg();
4034 pct2 = pic16_popGetTempReg();
4035 pct3 = pic16_popGetTempReg();
4037 label1 = newiTempLabel(NULL);
4038 label2 = newiTempLabel(NULL);
4039 label3 = newiTempLabel(NULL);
4041 /* the following algorithm is extracted from divuint.c */
4043 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4044 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4046 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4048 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4050 pic16_emitpLabel(label1->key);
4053 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4057 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4061 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4063 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4064 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4066 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4067 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4068 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4070 pic16_emitpLabel( label3->key );
4071 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4072 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4076 pic16_emitpLabel(label2->key);
4077 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4078 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4079 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4081 /* result is in wreg */
4082 if(AOP_TYPE(result) != AOP_ACC)
4083 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4085 pic16_popReleaseTempReg( pct3 );
4086 pic16_popReleaseTempReg( pct2 );
4087 pic16_popReleaseTempReg( pct1 );
4092 /* signed is a little bit more difficult */
4094 /* save the signs of the operands */
4095 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4097 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4098 pic16_emitcode("push","acc"); /* save it on the stack */
4100 /* now sign adjust for both left & right */
4101 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4103 lbl = newiTempLabel(NULL);
4104 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4105 pic16_emitcode("cpl","a");
4106 pic16_emitcode("inc","a");
4107 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4108 pic16_emitcode("mov","b,a");
4110 /* sign adjust left side */
4111 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4114 lbl = newiTempLabel(NULL);
4115 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4116 pic16_emitcode("cpl","a");
4117 pic16_emitcode("inc","a");
4118 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4120 /* now the division */
4121 pic16_emitcode("div","ab");
4122 /* we are interested in the lower order
4124 pic16_emitcode("mov","b,a");
4125 lbl = newiTempLabel(NULL);
4126 pic16_emitcode("pop","acc");
4127 /* if there was an over flow we don't
4128 adjust the sign of the result */
4129 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4130 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4132 pic16_emitcode("clr","a");
4133 pic16_emitcode("subb","a,b");
4134 pic16_emitcode("mov","b,a");
4135 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4137 /* now we are done */
4138 pic16_aopPut(AOP(result),"b",0);
4140 pic16_emitcode("mov","c,b.7");
4141 pic16_emitcode("subb","a,acc");
4144 pic16_aopPut(AOP(result),"a",offset++);
4148 /*-----------------------------------------------------------------*/
4149 /* genDiv - generates code for division */
4150 /*-----------------------------------------------------------------*/
4151 static void genDiv (iCode *ic)
4153 operand *left = IC_LEFT(ic);
4154 operand *right = IC_RIGHT(ic);
4155 operand *result= IC_RESULT(ic);
4158 /* Division is a very lengthy algorithm, so it is better
4159 * to call support routines than inlining algorithm.
4160 * Division functions written here just in case someone
4161 * wants to inline and not use the support libraries -- VR */
4163 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4164 /* assign the amsops */
4165 pic16_aopOp (left,ic,FALSE);
4166 pic16_aopOp (right,ic,FALSE);
4167 pic16_aopOp (result,ic,TRUE);
4169 /* special cases first */
4171 if (AOP_TYPE(left) == AOP_CRY &&
4172 AOP_TYPE(right)== AOP_CRY) {
4173 genDivbits(left,right,result);
4177 /* if both are of size == 1 */
4178 if (AOP_SIZE(left) == 1 &&
4179 AOP_SIZE(right) == 1 ) {
4180 genDivOneByte(left,right,result);
4184 /* should have been converted to function call */
4187 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4188 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4189 pic16_freeAsmop(result,NULL,ic,TRUE);
4192 /*-----------------------------------------------------------------*/
4193 /* genModbits :- modulus of bits */
4194 /*-----------------------------------------------------------------*/
4195 static void genModbits (operand *left,
4202 /* the result must be bit */
4203 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4204 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4208 pic16_emitcode("div","ab");
4209 pic16_emitcode("mov","a,b");
4210 pic16_emitcode("rrc","a");
4211 pic16_aopPut(AOP(result),"c",0);
4214 /*-----------------------------------------------------------------*/
4215 /* genModOneByte : 8 bit modulus */
4216 /*-----------------------------------------------------------------*/
4217 static void genModOneByte (operand *left,
4221 sym_link *opetype = operandType(result);
4225 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4226 /* signed or unsigned */
4227 if (SPEC_USIGN(opetype)) {
4228 /* unsigned is easy */
4229 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4230 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4232 pic16_emitcode("div","ab");
4233 pic16_aopPut(AOP(result),"b",0);
4237 /* signed is a little bit more difficult */
4239 /* save the signs of the operands */
4240 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4243 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4244 pic16_emitcode("push","acc"); /* save it on the stack */
4246 /* now sign adjust for both left & right */
4247 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4250 lbl = newiTempLabel(NULL);
4251 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4252 pic16_emitcode("cpl","a");
4253 pic16_emitcode("inc","a");
4254 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4255 pic16_emitcode("mov","b,a");
4257 /* sign adjust left side */
4258 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4261 lbl = newiTempLabel(NULL);
4262 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4263 pic16_emitcode("cpl","a");
4264 pic16_emitcode("inc","a");
4265 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4267 /* now the multiplication */
4268 pic16_emitcode("div","ab");
4269 /* we are interested in the lower order
4271 lbl = newiTempLabel(NULL);
4272 pic16_emitcode("pop","acc");
4273 /* if there was an over flow we don't
4274 adjust the sign of the result */
4275 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4276 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4278 pic16_emitcode("clr","a");
4279 pic16_emitcode("subb","a,b");
4280 pic16_emitcode("mov","b,a");
4281 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4283 /* now we are done */
4284 pic16_aopPut(AOP(result),"b",0);
4288 /*-----------------------------------------------------------------*/
4289 /* genMod - generates code for division */
4290 /*-----------------------------------------------------------------*/
4291 static void genMod (iCode *ic)
4293 operand *left = IC_LEFT(ic);
4294 operand *right = IC_RIGHT(ic);
4295 operand *result= IC_RESULT(ic);
4297 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4298 /* assign the amsops */
4299 pic16_aopOp (left,ic,FALSE);
4300 pic16_aopOp (right,ic,FALSE);
4301 pic16_aopOp (result,ic,TRUE);
4303 /* special cases first */
4305 if (AOP_TYPE(left) == AOP_CRY &&
4306 AOP_TYPE(right)== AOP_CRY) {
4307 genModbits(left,right,result);
4311 /* if both are of size == 1 */
4312 if (AOP_SIZE(left) == 1 &&
4313 AOP_SIZE(right) == 1 ) {
4314 genModOneByte(left,right,result);
4318 /* should have been converted to function call */
4322 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4323 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4324 pic16_freeAsmop(result,NULL,ic,TRUE);
4327 /*-----------------------------------------------------------------*/
4328 /* genIfxJump :- will create a jump depending on the ifx */
4329 /*-----------------------------------------------------------------*/
4331 note: May need to add parameter to indicate when a variable is in bit space.
4333 static void genIfxJump (iCode *ic, char *jval)
4336 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4337 /* if true label then we jump if condition
4339 if ( IC_TRUE(ic) ) {
4341 if(strcmp(jval,"a") == 0)
4343 else if (strcmp(jval,"c") == 0)
4346 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4347 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1));
4350 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4351 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4355 /* false label is present */
4356 if(strcmp(jval,"a") == 0)
4358 else if (strcmp(jval,"c") == 0)
4361 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4362 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1));
4365 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4366 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4371 /* mark the icode as generated */
4378 /*-----------------------------------------------------------------*/
4380 /*-----------------------------------------------------------------*/
4381 static void genSkip(iCode *ifx,int status_bit)
4383 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4387 if ( IC_TRUE(ifx) ) {
4388 switch(status_bit) {
4403 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4404 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4408 switch(status_bit) {
4422 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4423 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4430 /*-----------------------------------------------------------------*/
4432 /*-----------------------------------------------------------------*/
4433 static void genSkipc(resolvedIfx *rifx)
4435 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4445 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4446 rifx->generated = 1;
4449 /*-----------------------------------------------------------------*/
4451 /*-----------------------------------------------------------------*/
4452 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4454 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4459 if( (rifx->condition ^ invert_condition) & 1)
4464 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4465 rifx->generated = 1;
4469 /*-----------------------------------------------------------------*/
4471 /*-----------------------------------------------------------------*/
4472 static void genSkipz(iCode *ifx, int condition)
4483 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4485 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4488 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4490 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4495 /*-----------------------------------------------------------------*/
4497 /*-----------------------------------------------------------------*/
4498 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4504 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4506 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4509 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4510 rifx->generated = 1;
4514 /*-----------------------------------------------------------------*/
4515 /* genChkZeroes :- greater or less than comparison */
4516 /* For each byte in a literal that is zero, inclusive or the */
4517 /* the corresponding byte in the operand with W */
4518 /* returns true if any of the bytes are zero */
4519 /*-----------------------------------------------------------------*/
4520 static int genChkZeroes(operand *op, int lit, int size)
4527 i = (lit >> (size*8)) & 0xff;
4531 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4533 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4542 /*-----------------------------------------------------------------*/
4543 /* genCmp :- greater or less than comparison */
4544 /*-----------------------------------------------------------------*/
4545 static void genCmp (operand *left,operand *right,
4546 operand *result, iCode *ifx, int sign)
4548 int size; //, offset = 0 ;
4549 unsigned long lit = 0L,i = 0;
4550 resolvedIfx rFalseIfx;
4551 // resolvedIfx rTrueIfx;
4553 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4556 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4557 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4561 resolveIfx(&rFalseIfx,ifx);
4562 truelbl = newiTempLabel(NULL);
4563 size = max(AOP_SIZE(left),AOP_SIZE(right));
4565 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4569 /* if literal is on the right then swap with left */
4570 if ((AOP_TYPE(right) == AOP_LIT)) {
4571 operand *tmp = right ;
4572 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4573 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4576 lit = (lit - 1) & mask;
4579 rFalseIfx.condition ^= 1;
4582 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4583 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4587 //if(IC_TRUE(ifx) == NULL)
4588 /* if left & right are bit variables */
4589 if (AOP_TYPE(left) == AOP_CRY &&
4590 AOP_TYPE(right) == AOP_CRY ) {
4591 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4592 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4594 /* subtract right from left if at the
4595 end the carry flag is set then we know that
4596 left is greater than right */
4598 symbol *lbl = newiTempLabel(NULL);
4601 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4602 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+labelOffset, lbl->key+100+labelOffset);
4606 if(AOP_TYPE(right) == AOP_LIT) {
4608 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4610 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4617 genSkipCond(&rFalseIfx,left,size-1,7);
4619 /* no need to compare to 0...*/
4620 /* NOTE: this is a de-generate compare that most certainly
4621 * creates some dead code. */
4622 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4624 if(ifx) ifx->generated = 1;
4631 //i = (lit >> (size*8)) & 0xff;
4632 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4634 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4636 i = ((0-lit) & 0xff);
4639 /* lit is 0x7f, all signed chars are less than
4640 * this except for 0x7f itself */
4641 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4642 genSkipz2(&rFalseIfx,0);
4644 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4645 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4646 genSkipc(&rFalseIfx);
4651 genSkipz2(&rFalseIfx,1);
4653 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4654 genSkipc(&rFalseIfx);
4658 if(ifx) ifx->generated = 1;
4662 /* chars are out of the way. now do ints and longs */
4665 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4672 genSkipCond(&rFalseIfx,left,size,7);
4673 if(ifx) ifx->generated = 1;
4678 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4680 //rFalseIfx.condition ^= 1;
4681 //genSkipCond(&rFalseIfx,left,size,7);
4682 //rFalseIfx.condition ^= 1;
4684 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4685 if(rFalseIfx.condition)
4686 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4688 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4690 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4691 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4692 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4695 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4697 if(rFalseIfx.condition) {
4699 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4705 genSkipc(&rFalseIfx);
4706 pic16_emitpLabel(truelbl->key);
4707 if(ifx) ifx->generated = 1;
4714 if( (lit & 0xff) == 0) {
4715 /* lower byte is zero */
4716 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4717 i = ((lit >> 8) & 0xff) ^0x80;
4718 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4719 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4720 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4721 genSkipc(&rFalseIfx);
4724 if(ifx) ifx->generated = 1;
4729 /* Special cases for signed longs */
4730 if( (lit & 0xffffff) == 0) {
4731 /* lower byte is zero */
4732 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4733 i = ((lit >> 8*3) & 0xff) ^0x80;
4734 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4735 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4736 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4737 genSkipc(&rFalseIfx);
4740 if(ifx) ifx->generated = 1;
4748 if(lit & (0x80 << (size*8))) {
4749 /* lit is negative */
4750 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4752 //genSkipCond(&rFalseIfx,left,size,7);
4754 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4756 if(rFalseIfx.condition)
4757 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4759 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4763 /* lit is positive */
4764 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4765 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4766 if(rFalseIfx.condition)
4767 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4769 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4774 This works, but is only good for ints.
4775 It also requires a "known zero" register.
4776 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4777 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4778 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
4779 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4780 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4781 genSkipc(&rFalseIfx);
4783 pic16_emitpLabel(truelbl->key);
4784 if(ifx) ifx->generated = 1;
4788 /* There are no more special cases, so perform a general compare */
4790 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4791 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4795 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4797 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4799 //rFalseIfx.condition ^= 1;
4800 genSkipc(&rFalseIfx);
4802 pic16_emitpLabel(truelbl->key);
4804 if(ifx) ifx->generated = 1;
4811 /* sign is out of the way. So now do an unsigned compare */
4812 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4815 /* General case - compare to an unsigned literal on the right.*/
4817 i = (lit >> (size*8)) & 0xff;
4818 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4819 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4821 i = (lit >> (size*8)) & 0xff;
4824 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4826 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4828 /* this byte of the lit is zero,
4829 *if it's not the last then OR in the variable */
4831 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4836 pic16_emitpLabel(lbl->key);
4837 // pic16_emitpLabel(truelbl->key);
4838 //if(emitFinalCheck)
4839 genSkipc(&rFalseIfx);
4841 pic16_emitpLabel(truelbl->key);
4843 if(ifx) ifx->generated = 1;
4850 if(AOP_TYPE(left) == AOP_LIT) {
4851 //symbol *lbl = newiTempLabel(NULL);
4853 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4856 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4859 if((lit == 0) && (sign == 0)){
4862 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4864 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4866 genSkipz2(&rFalseIfx,0);
4867 if(ifx) ifx->generated = 1;
4874 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4875 /* degenerate compare can never be true */
4876 if(rFalseIfx.condition == 0)
4877 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4879 if(ifx) ifx->generated = 1;
4884 /* signed comparisons to a literal byte */
4886 int lp1 = (lit+1) & 0xff;
4888 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4891 rFalseIfx.condition ^= 1;
4892 genSkipCond(&rFalseIfx,right,0,7);
4895 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4896 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4897 genSkipz2(&rFalseIfx,1);
4900 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4901 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4902 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4903 rFalseIfx.condition ^= 1;
4904 genSkipc(&rFalseIfx);
4908 /* unsigned comparisons to a literal byte */
4910 switch(lit & 0xff ) {
4912 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4913 genSkipz2(&rFalseIfx,0);
4916 rFalseIfx.condition ^= 1;
4917 genSkipCond(&rFalseIfx,right,0,7);
4921 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4922 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4923 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4924 rFalseIfx.condition ^= 1;
4925 if (AOP_TYPE(result) == AOP_CRY)
4926 genSkipc(&rFalseIfx);
4928 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4929 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4935 if(ifx) ifx->generated = 1;
4936 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
4942 /* Size is greater than 1 */
4950 /* this means lit = 0xffffffff, or -1 */
4953 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4954 rFalseIfx.condition ^= 1;
4955 genSkipCond(&rFalseIfx,right,size,7);
4956 if(ifx) ifx->generated = 1;
4963 if(rFalseIfx.condition) {
4964 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4965 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4968 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4970 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4974 if(rFalseIfx.condition) {
4975 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4976 pic16_emitpLabel(truelbl->key);
4978 rFalseIfx.condition ^= 1;
4979 genSkipCond(&rFalseIfx,right,s,7);
4982 if(ifx) ifx->generated = 1;
4986 if((size == 1) && (0 == (lp1&0xff))) {
4987 /* lower byte of signed word is zero */
4988 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4989 i = ((lp1 >> 8) & 0xff) ^0x80;
4990 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4991 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4992 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4993 rFalseIfx.condition ^= 1;
4994 genSkipc(&rFalseIfx);
4997 if(ifx) ifx->generated = 1;
5001 if(lit & (0x80 << (size*8))) {
5002 /* Lit is less than zero */
5003 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5004 //rFalseIfx.condition ^= 1;
5005 //genSkipCond(&rFalseIfx,left,size,7);
5006 //rFalseIfx.condition ^= 1;
5007 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5008 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5010 if(rFalseIfx.condition)
5011 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5013 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5017 /* Lit is greater than or equal to zero */
5018 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5019 //rFalseIfx.condition ^= 1;
5020 //genSkipCond(&rFalseIfx,right,size,7);
5021 //rFalseIfx.condition ^= 1;
5023 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5024 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5026 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5027 if(rFalseIfx.condition)
5028 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5030 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5035 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5036 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5040 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5042 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5044 rFalseIfx.condition ^= 1;
5045 //rFalseIfx.condition = 1;
5046 genSkipc(&rFalseIfx);
5048 pic16_emitpLabel(truelbl->key);
5050 if(ifx) ifx->generated = 1;
5055 /* compare word or long to an unsigned literal on the right.*/
5060 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5063 break; /* handled above */
5066 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5068 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5069 genSkipz2(&rFalseIfx,0);
5073 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5075 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5078 if(rFalseIfx.condition)
5079 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5081 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5084 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5085 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5087 rFalseIfx.condition ^= 1;
5088 genSkipc(&rFalseIfx);
5091 pic16_emitpLabel(truelbl->key);
5093 if(ifx) ifx->generated = 1;
5099 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5100 i = (lit >> (size*8)) & 0xff;
5102 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5103 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5106 i = (lit >> (size*8)) & 0xff;
5109 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5111 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5113 /* this byte of the lit is zero,
5114 * if it's not the last then OR in the variable */
5116 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5121 pic16_emitpLabel(lbl->key);
5123 rFalseIfx.condition ^= 1;
5125 genSkipc(&rFalseIfx);
5129 pic16_emitpLabel(truelbl->key);
5130 if(ifx) ifx->generated = 1;
5134 /* Compare two variables */
5136 DEBUGpic16_emitcode(";sign","%d",sign);
5140 /* Sigh. thus sucks... */
5142 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5143 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5144 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5145 pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5146 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5147 pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5149 /* Signed char comparison */
5150 /* Special thanks to Nikolai Golovchenko for this snippet */
5151 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5152 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5153 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5154 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5155 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5156 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5158 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5159 genSkipc(&rFalseIfx);
5161 if(ifx) ifx->generated = 1;
5167 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5168 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5172 /* The rest of the bytes of a multi-byte compare */
5176 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5179 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5180 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5185 pic16_emitpLabel(lbl->key);
5187 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5188 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5189 (AOP_TYPE(result) == AOP_REG)) {
5190 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5191 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5193 genSkipc(&rFalseIfx);
5195 //genSkipc(&rFalseIfx);
5196 if(ifx) ifx->generated = 1;
5203 if ((AOP_TYPE(result) != AOP_CRY)
5204 && AOP_SIZE(result)) {
5205 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5206 // pic16_emitpLabel( rFalseIfx.lbl->key );
5208 pic16_outBitC(result);
5210 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5211 /* if the result is used in the next
5212 ifx conditional branch then generate
5213 code a little differently */
5215 genIfxJump (ifx,"c");
5217 pic16_outBitC(result);
5218 /* leave the result in acc */
5223 /*-----------------------------------------------------------------*/
5224 /* genCmpGt :- greater than comparison */
5225 /*-----------------------------------------------------------------*/
5226 static void genCmpGt (iCode *ic, iCode *ifx)
5228 operand *left, *right, *result;
5229 sym_link *letype , *retype;
5232 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5234 right= IC_RIGHT(ic);
5235 result = IC_RESULT(ic);
5237 letype = getSpec(operandType(left));
5238 retype =getSpec(operandType(right));
5239 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5240 /* assign the amsops */
5241 pic16_aopOp (left,ic,FALSE);
5242 pic16_aopOp (right,ic,FALSE);
5243 pic16_aopOp (result,ic,TRUE);
5245 genCmp(right, left, result, ifx, sign);
5247 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5248 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5249 pic16_freeAsmop(result,NULL,ic,TRUE);
5252 /*-----------------------------------------------------------------*/
5253 /* genCmpLt - less than comparisons */
5254 /*-----------------------------------------------------------------*/
5255 static void genCmpLt (iCode *ic, iCode *ifx)
5257 operand *left, *right, *result;
5258 sym_link *letype , *retype;
5261 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5263 right= IC_RIGHT(ic);
5264 result = IC_RESULT(ic);
5266 letype = getSpec(operandType(left));
5267 retype =getSpec(operandType(right));
5268 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5270 /* assign the amsops */
5271 pic16_aopOp (left,ic,FALSE);
5272 pic16_aopOp (right,ic,FALSE);
5273 pic16_aopOp (result,ic,TRUE);
5275 genCmp(left, right, result, ifx, sign);
5277 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5278 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5279 pic16_freeAsmop(result,NULL,ic,TRUE);
5284 // FIXME reenable literal optimisation when the pic16 port is stable
5286 /*-----------------------------------------------------------------*/
5287 /* genc16bit2lit - compare a 16 bit value to a literal */
5288 /*-----------------------------------------------------------------*/
5289 static void genc16bit2lit(operand *op, int lit, int offset)
5293 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
5294 if( (lit&0xff) == 0)
5299 switch( BYTEofLONG(lit,i)) {
5301 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5304 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5307 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5310 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5311 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5316 switch( BYTEofLONG(lit,i)) {
5318 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5322 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5326 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5329 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5331 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5340 /*-----------------------------------------------------------------*/
5341 /* gencjneshort - compare and jump if not equal */
5342 /*-----------------------------------------------------------------*/
5343 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5345 int size = max(AOP_SIZE(left),AOP_SIZE(right));
5347 int res_offset = 0; /* the result may be a different size then left or right */
5348 int res_size = AOP_SIZE(result);
5350 symbol *lbl, *lbl_done;
5352 unsigned long lit = 0L;
5353 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5355 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5356 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5358 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
5359 resolveIfx(&rIfx,ifx);
5360 lbl = newiTempLabel(NULL);
5361 lbl_done = newiTempLabel(NULL);
5364 /* if the left side is a literal or
5365 if the right is in a pointer register and left
5367 if ((AOP_TYPE(left) == AOP_LIT) ||
5368 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5373 if(AOP_TYPE(right) == AOP_LIT)
5374 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5376 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5377 preserve_result = 1;
5379 if(result && !preserve_result)
5382 for(i = 0; i < AOP_SIZE(result); i++)
5383 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5387 /* if the right side is a literal then anything goes */
5388 if (AOP_TYPE(right) == AOP_LIT &&
5389 AOP_TYPE(left) != AOP_DIR ) {
5392 genc16bit2lit(left, lit, 0);
5394 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5397 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5400 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5401 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5403 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5407 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5409 if(res_offset < res_size-1)
5417 /* if the right side is in a register or in direct space or
5418 if the left is a pointer register & right is not */
5419 else if (AOP_TYPE(right) == AOP_REG ||
5420 AOP_TYPE(right) == AOP_DIR ||
5421 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5422 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5423 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5424 int lbl_key = lbl->key;
5427 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5428 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5430 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5431 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5432 __FUNCTION__,__LINE__);
5436 /* switch(size) { */
5438 /* genc16bit2lit(left, lit, 0); */
5440 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5445 if((AOP_TYPE(left) == AOP_DIR) &&
5446 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5448 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5449 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5451 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5453 switch (lit & 0xff) {
5455 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5458 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5459 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5460 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5464 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5465 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5466 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5467 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5471 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5472 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5477 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5480 if(AOP_TYPE(result) == AOP_CRY) {
5481 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5486 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5488 /* fix me. probably need to check result size too */
5489 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5494 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5495 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5502 if(res_offset < res_size-1)
5507 } else if(AOP_TYPE(right) == AOP_REG &&
5508 AOP_TYPE(left) != AOP_DIR){
5511 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5512 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5513 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5518 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5520 if(res_offset < res_size-1)
5525 /* right is a pointer reg need both a & b */
5527 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5529 pic16_emitcode("mov","b,%s",l);
5530 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5531 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5536 if(result && preserve_result)
5539 for(i = 0; i < AOP_SIZE(result); i++)
5540 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5543 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5545 if(result && preserve_result)
5546 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5549 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5551 pic16_emitpLabel(lbl->key);
5553 if(result && preserve_result)
5556 for(i = 0; i < AOP_SIZE(result); i++)
5557 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5559 pic16_emitpLabel(lbl_done->key);
5562 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5570 /*-----------------------------------------------------------------*/
5571 /* gencjne - compare and jump if not equal */
5572 /*-----------------------------------------------------------------*/
5573 static void gencjne(operand *left, operand *right, iCode *ifx)
5575 symbol *tlbl = newiTempLabel(NULL);
5577 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5578 gencjneshort(left, right, lbl);
5580 pic16_emitcode("mov","a,%s",one);
5581 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5582 pic16_emitcode("","%05d_DS_:",lbl->key+100);
5583 pic16_emitcode("clr","a");
5584 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5586 pic16_emitpLabel(lbl->key);
5587 pic16_emitpLabel(tlbl->key);
5593 /*-----------------------------------------------------------------*/
5594 /* is_LitOp - check if operand has to be treated as literal */
5595 /*-----------------------------------------------------------------*/
5596 static bool is_LitOp(operand *op)
5598 return (AOP_TYPE(op) == AOP_LIT)
5599 || ( (AOP_TYPE(op) == AOP_PCODE)
5600 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5601 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));
5604 /*-----------------------------------------------------------------*/
5605 /* is_LitAOp - check if operand has to be treated as literal */
5606 /*-----------------------------------------------------------------*/
5607 static bool is_LitAOp(asmop *aop)
5609 return (aop->type == AOP_LIT)
5610 || ( (aop->type == AOP_PCODE)
5611 && ( (aop->aopu.pcop->type == PO_LITERAL)
5612 || (aop->aopu.pcop->type == PO_IMMEDIATE) ));
5617 /*-----------------------------------------------------------------*/
5618 /* genCmpEq - generates code for equal to */
5619 /*-----------------------------------------------------------------*/
5620 static void genCmpEq (iCode *ic, iCode *ifx)
5622 operand *left, *right, *result;
5623 symbol *falselbl = newiTempLabel(NULL);
5624 symbol *donelbl = newiTempLabel(NULL);
5626 int preserve_result = 0;
5627 int generate_result = 0;
5630 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5631 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5632 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5634 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5635 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5637 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5639 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5640 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5644 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5646 operand *tmp = right ;
5651 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5652 preserve_result = 1;
5654 if(result && AOP_SIZE(result))
5655 generate_result = 1;
5657 if(generate_result && !preserve_result)
5659 for(i = 0; i < AOP_SIZE(result); i++)
5660 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5663 for(i=0; i < AOP_SIZE(left); i++)
5665 if(AOP_TYPE(left) != AOP_ACC)
5668 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5670 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5673 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
5675 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
5677 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5682 if(generate_result && preserve_result)
5684 for(i = 0; i < AOP_SIZE(result); i++)
5685 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5689 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5691 if(generate_result && preserve_result)
5692 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5694 if(ifx && IC_TRUE(ifx))
5695 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5697 if(ifx && IC_FALSE(ifx))
5698 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5700 pic16_emitpLabel(falselbl->key);
5704 if(ifx && IC_FALSE(ifx))
5705 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5707 if(generate_result && preserve_result)
5709 for(i = 0; i < AOP_SIZE(result); i++)
5710 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5713 pic16_emitpLabel(donelbl->key);
5719 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5720 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5721 pic16_freeAsmop(result,NULL,ic,TRUE);
5727 // old version kept for reference
5729 /*-----------------------------------------------------------------*/
5730 /* genCmpEq - generates code for equal to */
5731 /*-----------------------------------------------------------------*/
5732 static void genCmpEq (iCode *ic, iCode *ifx)
5734 operand *left, *right, *result;
5735 unsigned long lit = 0L;
5737 symbol *falselbl = newiTempLabel(NULL);
5740 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5743 DEBUGpic16_emitcode ("; ifx is non-null","");
5745 DEBUGpic16_emitcode ("; ifx is null","");
5747 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5748 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5749 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5751 size = max(AOP_SIZE(left),AOP_SIZE(right));
5753 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5755 /* if literal, literal on the right or
5756 if the right is in a pointer register and left
5758 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
5759 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5760 operand *tmp = right ;
5766 if(ifx && !AOP_SIZE(result)){
5768 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
5769 /* if they are both bit variables */
5770 if (AOP_TYPE(left) == AOP_CRY &&
5771 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5772 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
5773 if(AOP_TYPE(right) == AOP_LIT){
5774 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5776 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5777 pic16_emitcode("cpl","c");
5778 } else if(lit == 1L) {
5779 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5781 pic16_emitcode("clr","c");
5783 /* AOP_TYPE(right) == AOP_CRY */
5785 symbol *lbl = newiTempLabel(NULL);
5786 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5787 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5788 pic16_emitcode("cpl","c");
5789 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5791 /* if true label then we jump if condition
5793 tlbl = newiTempLabel(NULL);
5794 if ( IC_TRUE(ifx) ) {
5795 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5796 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5798 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5799 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5801 pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5804 /* left and right are both bit variables, result is carry */
5807 resolveIfx(&rIfx,ifx);
5809 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5810 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5811 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5812 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5817 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
5819 /* They're not both bit variables. Is the right a literal? */
5820 if(AOP_TYPE(right) == AOP_LIT) {
5821 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5826 switch(lit & 0xff) {
5828 if ( IC_TRUE(ifx) ) {
5829 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5831 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5833 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5834 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5838 if ( IC_TRUE(ifx) ) {
5839 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5841 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5843 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5844 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5848 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5850 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5855 /* end of size == 1 */
5859 genc16bit2lit(left,lit,offset);
5862 /* end of size == 2 */
5867 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5868 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5869 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5870 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5873 /* search for patterns that can be optimized */
5875 genc16bit2lit(left,lit,0);
5879 emitSKPZ; // if hi word unequal
5881 emitSKPNZ; // if hi word equal
5883 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5884 genc16bit2lit(left,lit,2);
5887 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5888 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5892 pic16_emitpLabel(falselbl->key);
5901 } else if(AOP_TYPE(right) == AOP_CRY ) {
5902 /* we know the left is not a bit, but that the right is */
5903 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5904 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5905 pic16_popGet(AOP(right),offset));
5906 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5908 /* if the two are equal, then W will be 0 and the Z bit is set
5909 * we could test Z now, or go ahead and check the high order bytes if
5910 * the variable we're comparing is larger than a byte. */
5913 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5915 if ( IC_TRUE(ifx) ) {
5917 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5918 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5921 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5922 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5926 /* They're both variables that are larger than bits */
5929 tlbl = newiTempLabel(NULL);
5932 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5933 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5935 if ( IC_TRUE(ifx) ) {
5939 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5941 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5942 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5946 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5949 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5950 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5955 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5957 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5958 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5962 if(s>1 && IC_TRUE(ifx)) {
5963 pic16_emitpLabel(tlbl->key);
5964 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
5968 /* mark the icode as generated */
5973 /* if they are both bit variables */
5974 if (AOP_TYPE(left) == AOP_CRY &&
5975 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5976 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
5977 if(AOP_TYPE(right) == AOP_LIT){
5978 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5980 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5981 pic16_emitcode("cpl","c");
5982 } else if(lit == 1L) {
5983 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5985 pic16_emitcode("clr","c");
5987 /* AOP_TYPE(right) == AOP_CRY */
5989 symbol *lbl = newiTempLabel(NULL);
5990 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5991 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5992 pic16_emitcode("cpl","c");
5993 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5996 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5997 pic16_outBitC(result);
6001 genIfxJump (ifx,"c");
6004 /* if the result is used in an arithmetic operation
6005 then put the result in place */
6006 pic16_outBitC(result);
6009 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
6010 gencjne(left,right,result,ifx);
6013 gencjne(left,right,newiTempLabel(NULL));
6015 if(IC_TRUE(ifx)->key)
6016 gencjne(left,right,IC_TRUE(ifx)->key);
6018 gencjne(left,right,IC_FALSE(ifx)->key);
6022 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6023 pic16_aopPut(AOP(result),"a",0);
6028 genIfxJump (ifx,"a");
6032 /* if the result is used in an arithmetic operation
6033 then put the result in place */
6035 if (AOP_TYPE(result) != AOP_CRY)
6036 pic16_outAcc(result);
6038 /* leave the result in acc */
6042 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6043 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6044 pic16_freeAsmop(result,NULL,ic,TRUE);
6048 /*-----------------------------------------------------------------*/
6049 /* ifxForOp - returns the icode containing the ifx for operand */
6050 /*-----------------------------------------------------------------*/
6051 static iCode *ifxForOp ( operand *op, iCode *ic )
6053 /* if true symbol then needs to be assigned */
6054 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6055 if (IS_TRUE_SYMOP(op))
6058 /* if this has register type condition and
6059 the next instruction is ifx with the same operand
6060 and live to of the operand is upto the ifx only then */
6062 && ic->next->op == IFX
6063 && IC_COND(ic->next)->key == op->key
6064 && OP_SYMBOL(op)->liveTo <= ic->next->seq
6066 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6071 ic->next->op == IFX &&
6072 IC_COND(ic->next)->key == op->key) {
6073 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6077 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6079 ic->next->op == IFX)
6080 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6083 ic->next->op == IFX &&
6084 IC_COND(ic->next)->key == op->key) {
6085 DEBUGpic16_emitcode ("; "," key is okay");
6086 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6087 OP_SYMBOL(op)->liveTo,
6092 /* the code below is completely untested
6093 * it just allows ulong2fs.c compile -- VR */
6096 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6097 __FILE__, __FUNCTION__, __LINE__);
6099 /* if this has register type condition and
6100 the next instruction is ifx with the same operand
6101 and live to of the operand is upto the ifx only then */
6103 ic->next->op == IFX &&
6104 IC_COND(ic->next)->key == op->key &&
6105 OP_SYMBOL(op)->liveTo <= ic->next->seq )
6109 ic->next->op == IFX &&
6110 IC_COND(ic->next)->key == op->key) {
6111 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6115 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6116 __FILE__, __FUNCTION__, __LINE__);
6118 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
6123 /*-----------------------------------------------------------------*/
6124 /* genAndOp - for && operation */
6125 /*-----------------------------------------------------------------*/
6126 static void genAndOp (iCode *ic)
6128 operand *left,*right, *result;
6131 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6132 /* note here that && operations that are in an
6133 if statement are taken away by backPatchLabels
6134 only those used in arthmetic operations remain */
6135 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6136 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6137 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6139 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6141 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6142 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6143 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6145 /* if both are bit variables */
6146 /* if (AOP_TYPE(left) == AOP_CRY && */
6147 /* AOP_TYPE(right) == AOP_CRY ) { */
6148 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6149 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6150 /* pic16_outBitC(result); */
6152 /* tlbl = newiTempLabel(NULL); */
6153 /* pic16_toBoolean(left); */
6154 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6155 /* pic16_toBoolean(right); */
6156 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6157 /* pic16_outBitAcc(result); */
6160 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6161 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6162 pic16_freeAsmop(result,NULL,ic,TRUE);
6166 /*-----------------------------------------------------------------*/
6167 /* genOrOp - for || operation */
6168 /*-----------------------------------------------------------------*/
6171 modified this code, but it doesn't appear to ever get called
6174 static void genOrOp (iCode *ic)
6176 operand *left,*right, *result;
6179 /* note here that || operations that are in an
6180 if statement are taken away by backPatchLabels
6181 only those used in arthmetic operations remain */
6182 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6183 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6184 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6185 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6187 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6189 /* if both are bit variables */
6190 if (AOP_TYPE(left) == AOP_CRY &&
6191 AOP_TYPE(right) == AOP_CRY ) {
6192 pic16_emitcode("clrc","");
6193 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6194 AOP(left)->aopu.aop_dir,
6195 AOP(left)->aopu.aop_dir);
6196 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6197 AOP(right)->aopu.aop_dir,
6198 AOP(right)->aopu.aop_dir);
6199 pic16_emitcode("setc","");
6202 tlbl = newiTempLabel(NULL);
6203 pic16_toBoolean(left);
6205 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
6206 pic16_toBoolean(right);
6207 pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
6209 pic16_outBitAcc(result);
6212 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6213 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6214 pic16_freeAsmop(result,NULL,ic,TRUE);
6217 /*-----------------------------------------------------------------*/
6218 /* isLiteralBit - test if lit == 2^n */
6219 /*-----------------------------------------------------------------*/
6220 static int isLiteralBit(unsigned long lit)
6222 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6223 0x100L,0x200L,0x400L,0x800L,
6224 0x1000L,0x2000L,0x4000L,0x8000L,
6225 0x10000L,0x20000L,0x40000L,0x80000L,
6226 0x100000L,0x200000L,0x400000L,0x800000L,
6227 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6228 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6231 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6232 for(idx = 0; idx < 32; idx++)
6238 /*-----------------------------------------------------------------*/
6239 /* continueIfTrue - */
6240 /*-----------------------------------------------------------------*/
6241 static void continueIfTrue (iCode *ic)
6243 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6245 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6249 /*-----------------------------------------------------------------*/
6251 /*-----------------------------------------------------------------*/
6252 static void jumpIfTrue (iCode *ic)
6254 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6256 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6260 /*-----------------------------------------------------------------*/
6261 /* jmpTrueOrFalse - */
6262 /*-----------------------------------------------------------------*/
6263 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6265 // ugly but optimized by peephole
6266 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6268 symbol *nlbl = newiTempLabel(NULL);
6269 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
6270 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6271 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6272 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6275 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6276 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6281 /*-----------------------------------------------------------------*/
6282 /* genAnd - code for and */
6283 /*-----------------------------------------------------------------*/
6284 static void genAnd (iCode *ic, iCode *ifx)
6286 operand *left, *right, *result;
6288 unsigned long lit = 0L;
6293 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6294 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6295 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6296 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6298 resolveIfx(&rIfx,ifx);
6300 /* if left is a literal & right is not then exchange them */
6301 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6302 AOP_NEEDSACC(left)) {
6303 operand *tmp = right ;
6308 /* if result = right then exchange them */
6309 if(pic16_sameRegs(AOP(result),AOP(right))){
6310 operand *tmp = right ;
6315 /* if right is bit then exchange them */
6316 if (AOP_TYPE(right) == AOP_CRY &&
6317 AOP_TYPE(left) != AOP_CRY){
6318 operand *tmp = right ;
6322 if(AOP_TYPE(right) == AOP_LIT)
6323 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6325 size = AOP_SIZE(result);
6327 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6330 // result = bit & yy;
6331 if (AOP_TYPE(left) == AOP_CRY){
6332 // c = bit & literal;
6333 if(AOP_TYPE(right) == AOP_LIT){
6335 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6338 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6341 if(size && (AOP_TYPE(result) == AOP_CRY)){
6342 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6345 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6349 pic16_emitcode("clr","c");
6352 if (AOP_TYPE(right) == AOP_CRY){
6354 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6355 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6358 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6360 pic16_emitcode("rrc","a");
6361 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6367 pic16_outBitC(result);
6369 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6370 genIfxJump(ifx, "c");
6374 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6375 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6376 if((AOP_TYPE(right) == AOP_LIT) &&
6377 (AOP_TYPE(result) == AOP_CRY) &&
6378 (AOP_TYPE(left) != AOP_CRY)){
6379 int posbit = isLiteralBit(lit);
6383 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6386 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6392 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6393 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6395 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6396 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6399 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6400 size = AOP_SIZE(left);
6403 int bp = posbit, ofs=0;
6410 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6411 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0));
6415 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6416 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6418 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6425 symbol *tlbl = newiTempLabel(NULL);
6426 int sizel = AOP_SIZE(left);
6428 pic16_emitcode("setb","c");
6430 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6431 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6433 if((posbit = isLiteralBit(bytelit)) != 0)
6434 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6436 if(bytelit != 0x0FFL)
6437 pic16_emitcode("anl","a,%s",
6438 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6439 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6444 // bit = left & literal
6446 pic16_emitcode("clr","c");
6447 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6449 // if(left & literal)
6452 jmpTrueOrFalse(ifx, tlbl);
6456 pic16_outBitC(result);
6460 /* if left is same as result */
6461 if(pic16_sameRegs(AOP(result),AOP(left))){
6463 for(;size--; offset++,lit>>=8) {
6464 if(AOP_TYPE(right) == AOP_LIT){
6465 switch(lit & 0xff) {
6467 /* and'ing with 0 has clears the result */
6468 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6469 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6472 /* and'ing with 0xff is a nop when the result and left are the same */
6477 int p = my_powof2( (~lit) & 0xff );
6479 /* only one bit is set in the literal, so use a bcf instruction */
6480 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6481 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6484 pic16_emitcode("movlw","0x%x", (lit & 0xff));
6485 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6486 if(know_W != (lit&0xff))
6487 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6489 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6494 if (AOP_TYPE(left) == AOP_ACC) {
6495 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6497 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6498 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6505 // left & result in different registers
6506 if(AOP_TYPE(result) == AOP_CRY){
6508 // if(size), result in bit
6509 // if(!size && ifx), conditional oper: if(left & right)
6510 symbol *tlbl = newiTempLabel(NULL);
6511 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6513 pic16_emitcode("setb","c");
6515 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6516 pic16_emitcode("anl","a,%s",
6517 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6518 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6523 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6524 pic16_outBitC(result);
6526 jmpTrueOrFalse(ifx, tlbl);
6528 for(;(size--);offset++) {
6530 // result = left & right
6531 if(AOP_TYPE(right) == AOP_LIT){
6532 int t = (lit >> (offset*8)) & 0x0FFL;
6535 pic16_emitcode("clrf","%s",
6536 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6537 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6540 pic16_emitcode("movf","%s,w",
6541 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6542 pic16_emitcode("movwf","%s",
6543 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6544 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6545 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6548 pic16_emitcode("movlw","0x%x",t);
6549 pic16_emitcode("andwf","%s,w",
6550 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6551 pic16_emitcode("movwf","%s",
6552 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6554 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6555 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6556 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6561 if (AOP_TYPE(left) == AOP_ACC) {
6562 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6563 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6565 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6566 pic16_emitcode("andwf","%s,w",
6567 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6568 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6569 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6571 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6572 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6578 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6579 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6580 pic16_freeAsmop(result,NULL,ic,TRUE);
6583 /*-----------------------------------------------------------------*/
6584 /* genOr - code for or */
6585 /*-----------------------------------------------------------------*/
6586 static void genOr (iCode *ic, iCode *ifx)
6588 operand *left, *right, *result;
6590 unsigned long lit = 0L;
6592 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6594 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6595 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6596 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6598 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6600 /* if left is a literal & right is not then exchange them */
6601 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6602 AOP_NEEDSACC(left)) {
6603 operand *tmp = right ;
6608 /* if result = right then exchange them */
6609 if(pic16_sameRegs(AOP(result),AOP(right))){
6610 operand *tmp = right ;
6615 /* if right is bit then exchange them */
6616 if (AOP_TYPE(right) == AOP_CRY &&
6617 AOP_TYPE(left) != AOP_CRY){
6618 operand *tmp = right ;
6623 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6625 if(AOP_TYPE(right) == AOP_LIT)
6626 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6628 size = AOP_SIZE(result);
6632 if (AOP_TYPE(left) == AOP_CRY){
6633 if(AOP_TYPE(right) == AOP_LIT){
6634 // c = bit & literal;
6636 // lit != 0 => result = 1
6637 if(AOP_TYPE(result) == AOP_CRY){
6639 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6640 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6641 // AOP(result)->aopu.aop_dir,
6642 // AOP(result)->aopu.aop_dir);
6644 continueIfTrue(ifx);
6648 // lit == 0 => result = left
6649 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6651 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6654 if (AOP_TYPE(right) == AOP_CRY){
6655 if(pic16_sameRegs(AOP(result),AOP(left))){
6657 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6658 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6659 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6661 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6662 AOP(result)->aopu.aop_dir,
6663 AOP(result)->aopu.aop_dir);
6664 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6665 AOP(right)->aopu.aop_dir,
6666 AOP(right)->aopu.aop_dir);
6667 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6668 AOP(result)->aopu.aop_dir,
6669 AOP(result)->aopu.aop_dir);
6671 if( AOP_TYPE(result) == AOP_ACC) {
6672 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6673 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6674 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6675 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6679 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6680 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6681 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6682 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6684 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6685 AOP(result)->aopu.aop_dir,
6686 AOP(result)->aopu.aop_dir);
6687 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6688 AOP(right)->aopu.aop_dir,
6689 AOP(right)->aopu.aop_dir);
6690 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6691 AOP(left)->aopu.aop_dir,
6692 AOP(left)->aopu.aop_dir);
6693 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6694 AOP(result)->aopu.aop_dir,
6695 AOP(result)->aopu.aop_dir);
6700 symbol *tlbl = newiTempLabel(NULL);
6701 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6704 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6705 if( AOP_TYPE(right) == AOP_ACC) {
6706 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6708 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6709 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6714 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6715 pic16_emitcode(";XXX setb","c");
6716 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6717 AOP(left)->aopu.aop_dir,tlbl->key+100);
6718 pic16_toBoolean(right);
6719 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6720 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6721 jmpTrueOrFalse(ifx, tlbl);
6725 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6732 pic16_outBitC(result);
6734 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6735 genIfxJump(ifx, "c");
6739 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6740 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6741 if((AOP_TYPE(right) == AOP_LIT) &&
6742 (AOP_TYPE(result) == AOP_CRY) &&
6743 (AOP_TYPE(left) != AOP_CRY)){
6745 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6748 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6750 continueIfTrue(ifx);
6753 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6754 // lit = 0, result = boolean(left)
6756 pic16_emitcode(";XXX setb","c");
6757 pic16_toBoolean(right);
6759 symbol *tlbl = newiTempLabel(NULL);
6760 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6762 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6764 genIfxJump (ifx,"a");
6768 pic16_outBitC(result);
6772 /* if left is same as result */
6773 if(pic16_sameRegs(AOP(result),AOP(left))){
6775 for(;size--; offset++,lit>>=8) {
6776 if(AOP_TYPE(right) == AOP_LIT){
6777 if((lit & 0xff) == 0)
6778 /* or'ing with 0 has no effect */
6781 int p = my_powof2(lit & 0xff);
6783 /* only one bit is set in the literal, so use a bsf instruction */
6784 pic16_emitpcode(POC_BSF,
6785 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6787 if(know_W != (lit & 0xff))
6788 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6789 know_W = lit & 0xff;
6790 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6795 if (AOP_TYPE(left) == AOP_ACC) {
6796 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
6797 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6799 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6800 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6802 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6803 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6809 // left & result in different registers
6810 if(AOP_TYPE(result) == AOP_CRY){
6812 // if(size), result in bit
6813 // if(!size && ifx), conditional oper: if(left | right)
6814 symbol *tlbl = newiTempLabel(NULL);
6815 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6816 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6820 pic16_emitcode(";XXX setb","c");
6822 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6823 pic16_emitcode(";XXX orl","a,%s",
6824 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6825 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6830 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6831 pic16_outBitC(result);
6833 jmpTrueOrFalse(ifx, tlbl);
6834 } else for(;(size--);offset++){
6836 // result = left & right
6837 if(AOP_TYPE(right) == AOP_LIT){
6838 int t = (lit >> (offset*8)) & 0x0FFL;
6841 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
6842 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6844 pic16_emitcode("movf","%s,w",
6845 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6846 pic16_emitcode("movwf","%s",
6847 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6850 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6851 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6852 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6854 pic16_emitcode("movlw","0x%x",t);
6855 pic16_emitcode("iorwf","%s,w",
6856 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6857 pic16_emitcode("movwf","%s",
6858 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6864 // faster than result <- left, anl result,right
6865 // and better if result is SFR
6866 if (AOP_TYPE(left) == AOP_ACC) {
6867 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
6868 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6870 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6871 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6873 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6874 pic16_emitcode("iorwf","%s,w",
6875 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6877 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6878 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6883 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6884 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6885 pic16_freeAsmop(result,NULL,ic,TRUE);
6888 /*-----------------------------------------------------------------*/
6889 /* genXor - code for xclusive or */
6890 /*-----------------------------------------------------------------*/
6891 static void genXor (iCode *ic, iCode *ifx)
6893 operand *left, *right, *result;
6895 unsigned long lit = 0L;
6897 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6899 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6900 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6901 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6903 /* if left is a literal & right is not ||
6904 if left needs acc & right does not */
6905 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6906 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6907 operand *tmp = right ;
6912 /* if result = right then exchange them */
6913 if(pic16_sameRegs(AOP(result),AOP(right))){
6914 operand *tmp = right ;
6919 /* if right is bit then exchange them */
6920 if (AOP_TYPE(right) == AOP_CRY &&
6921 AOP_TYPE(left) != AOP_CRY){
6922 operand *tmp = right ;
6926 if(AOP_TYPE(right) == AOP_LIT)
6927 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6929 size = AOP_SIZE(result);
6933 if (AOP_TYPE(left) == AOP_CRY){
6934 if(AOP_TYPE(right) == AOP_LIT){
6935 // c = bit & literal;
6937 // lit>>1 != 0 => result = 1
6938 if(AOP_TYPE(result) == AOP_CRY){
6940 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
6941 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6943 continueIfTrue(ifx);
6946 pic16_emitcode("setb","c");
6950 // lit == 0, result = left
6951 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6953 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6955 // lit == 1, result = not(left)
6956 if(size && pic16_sameRegs(AOP(result),AOP(left))){
6957 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
6958 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
6959 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6962 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6963 pic16_emitcode("cpl","c");
6970 symbol *tlbl = newiTempLabel(NULL);
6971 if (AOP_TYPE(right) == AOP_CRY){
6973 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6976 int sizer = AOP_SIZE(right);
6978 // if val>>1 != 0, result = 1
6979 pic16_emitcode("setb","c");
6981 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6983 // test the msb of the lsb
6984 pic16_emitcode("anl","a,#0xfe");
6985 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6989 pic16_emitcode("rrc","a");
6991 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6992 pic16_emitcode("cpl","c");
6993 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6998 pic16_outBitC(result);
7000 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7001 genIfxJump(ifx, "c");
7005 if(pic16_sameRegs(AOP(result),AOP(left))){
7006 /* if left is same as result */
7007 for(;size--; offset++) {
7008 if(AOP_TYPE(right) == AOP_LIT){
7009 int t = (lit >> (offset*8)) & 0x0FFL;
7013 if (IS_AOP_PREG(left)) {
7014 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7015 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7016 pic16_aopPut(AOP(result),"a",offset);
7018 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7019 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7020 pic16_emitcode("xrl","%s,%s",
7021 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7022 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7025 if (AOP_TYPE(left) == AOP_ACC)
7026 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7028 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7029 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7031 if (IS_AOP_PREG(left)) {
7032 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7033 pic16_aopPut(AOP(result),"a",offset);
7035 pic16_emitcode("xrl","%s,a",
7036 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7042 // left & result in different registers
7043 if(AOP_TYPE(result) == AOP_CRY){
7045 // if(size), result in bit
7046 // if(!size && ifx), conditional oper: if(left ^ right)
7047 symbol *tlbl = newiTempLabel(NULL);
7048 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7050 pic16_emitcode("setb","c");
7052 if((AOP_TYPE(right) == AOP_LIT) &&
7053 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7054 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7056 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7057 pic16_emitcode("xrl","a,%s",
7058 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7060 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7065 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7066 pic16_outBitC(result);
7068 jmpTrueOrFalse(ifx, tlbl);
7069 } else for(;(size--);offset++){
7071 // result = left & right
7072 if(AOP_TYPE(right) == AOP_LIT){
7073 int t = (lit >> (offset*8)) & 0x0FFL;
7076 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7077 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7078 pic16_emitcode("movf","%s,w",
7079 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7080 pic16_emitcode("movwf","%s",
7081 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7084 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7085 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7086 pic16_emitcode("comf","%s,w",
7087 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7088 pic16_emitcode("movwf","%s",
7089 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7092 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7093 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7094 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7095 pic16_emitcode("movlw","0x%x",t);
7096 pic16_emitcode("xorwf","%s,w",
7097 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7098 pic16_emitcode("movwf","%s",
7099 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7105 // faster than result <- left, anl result,right
7106 // and better if result is SFR
7107 if (AOP_TYPE(left) == AOP_ACC) {
7108 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7109 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7111 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7112 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7113 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7114 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7116 if ( AOP_TYPE(result) != AOP_ACC){
7117 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7118 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7124 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7125 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7126 pic16_freeAsmop(result,NULL,ic,TRUE);
7129 /*-----------------------------------------------------------------*/
7130 /* genInline - write the inline code out */
7131 /*-----------------------------------------------------------------*/
7132 static void genInline (iCode *ic)
7134 char *buffer, *bp, *bp1;
7136 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7138 _G.inLine += (!options.asmpeep);
7140 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7141 strcpy(buffer,IC_INLINE(ic));
7143 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7145 /* emit each line as a code */
7151 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7159 /* print label, use this special format with NULL directive
7160 * to denote that the argument should not be indented with tab */
7161 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7168 if ((bp1 != bp) && *bp1)
7169 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7174 _G.inLine -= (!options.asmpeep);
7177 /*-----------------------------------------------------------------*/
7178 /* genRRC - rotate right with carry */
7179 /*-----------------------------------------------------------------*/
7180 static void genRRC (iCode *ic)
7182 operand *left , *result ;
7183 int size, offset = 0, same;
7185 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7187 /* rotate right with carry */
7189 result=IC_RESULT(ic);
7190 pic16_aopOp (left,ic,FALSE);
7191 pic16_aopOp (result,ic,FALSE);
7193 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7195 same = pic16_sameRegs(AOP(result),AOP(left));
7197 size = AOP_SIZE(result);
7199 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7201 /* get the lsb and put it into the carry */
7202 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7209 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7211 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7212 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7218 pic16_freeAsmop(left,NULL,ic,TRUE);
7219 pic16_freeAsmop(result,NULL,ic,TRUE);
7222 /*-----------------------------------------------------------------*/
7223 /* genRLC - generate code for rotate left with carry */
7224 /*-----------------------------------------------------------------*/
7225 static void genRLC (iCode *ic)
7227 operand *left , *result ;
7228 int size, offset = 0;
7231 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7232 /* rotate right with carry */
7234 result=IC_RESULT(ic);
7235 pic16_aopOp (left,ic,FALSE);
7236 pic16_aopOp (result,ic,FALSE);
7238 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7240 same = pic16_sameRegs(AOP(result),AOP(left));
7242 /* move it to the result */
7243 size = AOP_SIZE(result);
7245 /* get the msb and put it into the carry */
7246 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7253 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7255 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7256 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7263 pic16_freeAsmop(left,NULL,ic,TRUE);
7264 pic16_freeAsmop(result,NULL,ic,TRUE);
7268 /* gpasm can get the highest order bit with HIGH/UPPER
7269 * so the following probably is not needed -- VR */
7271 /*-----------------------------------------------------------------*/
7272 /* genGetHbit - generates code get highest order bit */
7273 /*-----------------------------------------------------------------*/
7274 static void genGetHbit (iCode *ic)
7276 operand *left, *result;
7278 result=IC_RESULT(ic);
7279 pic16_aopOp (left,ic,FALSE);
7280 pic16_aopOp (result,ic,FALSE);
7282 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7283 /* get the highest order byte into a */
7284 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7285 if(AOP_TYPE(result) == AOP_CRY){
7286 pic16_emitcode("rlc","a");
7287 pic16_outBitC(result);
7290 pic16_emitcode("rl","a");
7291 pic16_emitcode("anl","a,#0x01");
7292 pic16_outAcc(result);
7296 pic16_freeAsmop(left,NULL,ic,TRUE);
7297 pic16_freeAsmop(result,NULL,ic,TRUE);
7301 /*-----------------------------------------------------------------*/
7302 /* AccRol - rotate left accumulator by known count */
7303 /*-----------------------------------------------------------------*/
7304 static void AccRol (int shCount)
7306 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7307 shCount &= 0x0007; // shCount : 0..7
7312 pic16_emitcode("rl","a");
7315 pic16_emitcode("rl","a");
7316 pic16_emitcode("rl","a");
7319 pic16_emitcode("swap","a");
7320 pic16_emitcode("rr","a");
7323 pic16_emitcode("swap","a");
7326 pic16_emitcode("swap","a");
7327 pic16_emitcode("rl","a");
7330 pic16_emitcode("rr","a");
7331 pic16_emitcode("rr","a");
7334 pic16_emitcode("rr","a");
7340 /*-----------------------------------------------------------------*/
7341 /* AccLsh - left shift accumulator by known count */
7342 /*-----------------------------------------------------------------*/
7343 static void AccLsh (int shCount)
7345 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7351 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7354 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7355 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7358 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7359 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7362 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7365 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7366 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7369 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7370 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7373 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7377 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7380 /*-----------------------------------------------------------------*/
7381 /* AccRsh - right shift accumulator by known count */
7382 /*-----------------------------------------------------------------*/
7383 static void AccRsh (int shCount, int andmask)
7385 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7390 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7391 // andmask = 0; /* no need */
7394 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7395 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7396 // andmask = 0; /* no need */
7399 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7400 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7403 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7406 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7407 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7410 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7411 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7414 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7419 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7421 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7425 /*-----------------------------------------------------------------*/
7426 /* AccSRsh - signed right shift accumulator by known count */
7427 /*-----------------------------------------------------------------*/
7428 static void AccSRsh (int shCount)
7431 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7434 pic16_emitcode("mov","c,acc.7");
7435 pic16_emitcode("rrc","a");
7436 } else if(shCount == 2){
7437 pic16_emitcode("mov","c,acc.7");
7438 pic16_emitcode("rrc","a");
7439 pic16_emitcode("mov","c,acc.7");
7440 pic16_emitcode("rrc","a");
7442 tlbl = newiTempLabel(NULL);
7443 /* rotate right accumulator */
7444 AccRol(8 - shCount);
7445 /* and kill the higher order bits */
7446 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7447 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7448 pic16_emitcode("orl","a,#0x%02x",
7449 (unsigned char)~SRMask[shCount]);
7450 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7455 /*-----------------------------------------------------------------*/
7456 /* shiftR1Left2Result - shift right one byte from left to result */
7457 /*-----------------------------------------------------------------*/
7458 static void shiftR1Left2ResultSigned (operand *left, int offl,
7459 operand *result, int offr,
7464 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7466 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7470 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7472 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7474 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7475 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7481 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7483 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7485 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7486 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7488 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7489 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7495 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7497 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7498 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7501 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7502 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7503 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7505 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7506 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7508 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7512 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7513 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7514 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7515 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
7516 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7520 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7522 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7523 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7525 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7526 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
7527 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7528 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
7529 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7534 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7535 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7536 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7537 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7538 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7539 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7541 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7542 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7543 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7544 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7545 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7551 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7552 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7553 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7554 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7556 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7557 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7558 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7566 /*-----------------------------------------------------------------*/
7567 /* shiftR1Left2Result - shift right one byte from left to result */
7568 /*-----------------------------------------------------------------*/
7569 static void shiftR1Left2Result (operand *left, int offl,
7570 operand *result, int offr,
7571 int shCount, int sign)
7575 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7577 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7579 /* Copy the msb into the carry if signed. */
7581 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7591 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7593 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7594 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7600 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7602 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7603 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7606 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7611 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7613 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7614 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7617 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7618 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7619 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7620 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7624 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7625 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7626 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7630 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7631 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7632 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7634 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7639 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7640 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7641 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7642 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7643 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7648 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7649 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7650 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7659 /*-----------------------------------------------------------------*/
7660 /* shiftL1Left2Result - shift left one byte from left to result */
7661 /*-----------------------------------------------------------------*/
7662 static void shiftL1Left2Result (operand *left, int offl,
7663 operand *result, int offr, int shCount)
7668 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7670 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7671 DEBUGpic16_emitcode ("; ***","same = %d",same);
7672 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7674 /* shift left accumulator */
7675 //AccLsh(shCount); // don't comment out just yet...
7676 // pic16_aopPut(AOP(result),"a",offr);
7680 /* Shift left 1 bit position */
7681 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7683 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7685 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7686 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7690 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7691 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7692 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7693 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7696 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7697 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7698 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7699 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7700 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7703 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7704 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7705 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7708 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7709 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7710 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7711 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7714 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7715 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7716 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7717 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7718 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7721 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7722 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7723 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7727 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7732 /*-----------------------------------------------------------------*/
7733 /* movLeft2Result - move byte from left to result */
7734 /*-----------------------------------------------------------------*/
7735 static void movLeft2Result (operand *left, int offl,
7736 operand *result, int offr)
7739 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7740 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7741 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7743 if (*l == '@' && (IS_AOP_PREG(result))) {
7744 pic16_emitcode("mov","a,%s",l);
7745 pic16_aopPut(AOP(result),"a",offr);
7747 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7748 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7753 /*-----------------------------------------------------------------*/
7754 /* shiftL2Left2Result - shift left two bytes from left to result */
7755 /*-----------------------------------------------------------------*/
7756 static void shiftL2Left2Result (operand *left, int offl,
7757 operand *result, int offr, int shCount)
7759 int same = pic16_sameRegs(AOP(result), AOP(left));
7762 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7764 if (same && (offl != offr)) { // shift bytes
7767 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7768 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7770 } else { // just treat as different later on
7783 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7784 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7785 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7789 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7790 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7796 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7797 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7798 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7799 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7800 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7801 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7802 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7804 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7805 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7809 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7810 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7811 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7812 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7813 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7814 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7815 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7816 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7817 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7818 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7821 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7822 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7823 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7824 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7825 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7835 /* note, use a mov/add for the shift since the mov has a
7836 chance of getting optimized out */
7837 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7838 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7839 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7840 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7841 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7845 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7846 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7852 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7853 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7854 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7855 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7856 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7857 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7858 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7859 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7863 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7864 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7868 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7869 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7870 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7871 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7873 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7874 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7875 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7876 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7877 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7878 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7879 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7880 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7883 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7884 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7885 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7886 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7887 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7892 /*-----------------------------------------------------------------*/
7893 /* shiftR2Left2Result - shift right two bytes from left to result */
7894 /*-----------------------------------------------------------------*/
7895 static void shiftR2Left2Result (operand *left, int offl,
7896 operand *result, int offr,
7897 int shCount, int sign)
7899 int same = pic16_sameRegs(AOP(result), AOP(left));
7901 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7903 if (same && (offl != offr)) { // shift right bytes
7906 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7907 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7909 } else { // just treat as different later on
7921 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7926 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7927 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7929 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7930 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7931 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7932 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7937 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7940 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7941 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7948 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7949 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7950 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7952 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7953 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7954 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7955 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7957 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7958 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7959 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7961 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7962 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7963 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7964 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7965 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7969 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7970 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7974 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7975 pic16_emitpcode(POC_BTFSC,
7976 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7977 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7985 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7986 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7988 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7989 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7990 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7991 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7993 pic16_emitpcode(POC_BTFSC,
7994 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7995 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7997 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7998 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7999 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8000 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8002 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8003 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8004 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8005 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8006 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8007 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8008 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8009 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8011 pic16_emitpcode(POC_BTFSC,
8012 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
8013 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8015 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8016 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8023 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8024 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8025 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8026 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8029 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8031 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8036 /*-----------------------------------------------------------------*/
8037 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8038 /*-----------------------------------------------------------------*/
8039 static void shiftLLeftOrResult (operand *left, int offl,
8040 operand *result, int offr, int shCount)
8042 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8044 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8045 /* shift left accumulator */
8047 /* or with result */
8048 /* back to result */
8049 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8052 /*-----------------------------------------------------------------*/
8053 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8054 /*-----------------------------------------------------------------*/
8055 static void shiftRLeftOrResult (operand *left, int offl,
8056 operand *result, int offr, int shCount)
8058 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8060 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8061 /* shift right accumulator */
8063 /* or with result */
8064 /* back to result */
8065 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8068 /*-----------------------------------------------------------------*/
8069 /* genlshOne - left shift a one byte quantity by known count */
8070 /*-----------------------------------------------------------------*/
8071 static void genlshOne (operand *result, operand *left, int shCount)
8073 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8074 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8077 /*-----------------------------------------------------------------*/
8078 /* genlshTwo - left shift two bytes by known amount != 0 */
8079 /*-----------------------------------------------------------------*/
8080 static void genlshTwo (operand *result,operand *left, int shCount)
8084 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8085 size = pic16_getDataSize(result);
8087 /* if shCount >= 8 */
8093 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8095 movLeft2Result(left, LSB, result, MSB16);
8097 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8100 /* 1 <= shCount <= 7 */
8103 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8105 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8109 /*-----------------------------------------------------------------*/
8110 /* shiftLLong - shift left one long from left to result */
8111 /* offr = LSB or MSB16 */
8112 /*-----------------------------------------------------------------*/
8113 static void shiftLLong (operand *left, operand *result, int offr )
8115 int size = AOP_SIZE(result);
8116 int same = pic16_sameRegs(AOP(left),AOP(result));
8119 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8121 if (same && (offr == MSB16)) { //shift one byte
8122 for(i=size-1;i>=MSB16;i--) {
8123 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8124 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8127 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8130 if (size >= LSB+offr ){
8132 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8134 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8135 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8139 if(size >= MSB16+offr){
8141 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8143 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8144 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8148 if(size >= MSB24+offr){
8150 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8152 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8153 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8157 if(size > MSB32+offr){
8159 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8161 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8162 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8166 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8170 /*-----------------------------------------------------------------*/
8171 /* genlshFour - shift four byte by a known amount != 0 */
8172 /*-----------------------------------------------------------------*/
8173 static void genlshFour (operand *result, operand *left, int shCount)
8177 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8178 size = AOP_SIZE(result);
8180 /* if shifting more that 3 bytes */
8181 if (shCount >= 24 ) {
8184 /* lowest order of left goes to the highest
8185 order of the destination */
8186 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8188 movLeft2Result(left, LSB, result, MSB32);
8190 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8191 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8192 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8197 /* more than two bytes */
8198 else if ( shCount >= 16 ) {
8199 /* lower order two bytes goes to higher order two bytes */
8201 /* if some more remaining */
8203 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8205 movLeft2Result(left, MSB16, result, MSB32);
8206 movLeft2Result(left, LSB, result, MSB24);
8208 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8209 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8213 /* if more than 1 byte */
8214 else if ( shCount >= 8 ) {
8215 /* lower order three bytes goes to higher order three bytes */
8219 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8221 movLeft2Result(left, LSB, result, MSB16);
8223 else{ /* size = 4 */
8225 movLeft2Result(left, MSB24, result, MSB32);
8226 movLeft2Result(left, MSB16, result, MSB24);
8227 movLeft2Result(left, LSB, result, MSB16);
8228 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8230 else if(shCount == 1)
8231 shiftLLong(left, result, MSB16);
8233 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8234 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8235 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8236 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8241 /* 1 <= shCount <= 7 */
8242 else if(shCount <= 3)
8244 shiftLLong(left, result, LSB);
8245 while(--shCount >= 1)
8246 shiftLLong(result, result, LSB);
8248 /* 3 <= shCount <= 7, optimize */
8250 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8251 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8252 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8256 /*-----------------------------------------------------------------*/
8257 /* genLeftShiftLiteral - left shifting by known count */
8258 /*-----------------------------------------------------------------*/
8259 static void genLeftShiftLiteral (operand *left,
8264 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8267 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8268 pic16_freeAsmop(right,NULL,ic,TRUE);
8270 pic16_aopOp(left,ic,FALSE);
8271 pic16_aopOp(result,ic,FALSE);
8273 size = getSize(operandType(result));
8276 pic16_emitcode("; shift left ","result %d, left %d",size,
8280 /* I suppose that the left size >= result size */
8283 movLeft2Result(left, size, result, size);
8287 else if(shCount >= (size * 8))
8289 pic16_aopPut(AOP(result),zero,size);
8293 genlshOne (result,left,shCount);
8298 genlshTwo (result,left,shCount);
8302 genlshFour (result,left,shCount);
8306 pic16_freeAsmop(left,NULL,ic,TRUE);
8307 pic16_freeAsmop(result,NULL,ic,TRUE);
8310 /*-----------------------------------------------------------------*
8311 * genMultiAsm - repeat assembly instruction for size of register.
8312 * if endian == 1, then the high byte (i.e base address + size of
8313 * register) is used first else the low byte is used first;
8314 *-----------------------------------------------------------------*/
8315 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8320 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8333 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
8338 /*-----------------------------------------------------------------*/
8339 /* genLeftShift - generates code for left shifting */
8340 /*-----------------------------------------------------------------*/
8341 static void genLeftShift (iCode *ic)
8343 operand *left,*right, *result;
8346 symbol *tlbl , *tlbl1;
8349 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8351 right = IC_RIGHT(ic);
8353 result = IC_RESULT(ic);
8355 pic16_aopOp(right,ic,FALSE);
8357 /* if the shift count is known then do it
8358 as efficiently as possible */
8359 if (AOP_TYPE(right) == AOP_LIT) {
8360 genLeftShiftLiteral (left,right,result,ic);
8364 /* shift count is unknown then we have to form
8365 a loop get the loop count in B : Note: we take
8366 only the lower order byte since shifting
8367 more that 32 bits make no sense anyway, ( the
8368 largest size of an object can be only 32 bits ) */
8371 pic16_aopOp(left,ic,FALSE);
8372 pic16_aopOp(result,ic,FALSE);
8374 /* now move the left to the result if they are not the
8376 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8377 AOP_SIZE(result) > 1) {
8379 size = AOP_SIZE(result);
8382 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8383 if (*l == '@' && (IS_AOP_PREG(result))) {
8385 pic16_emitcode("mov","a,%s",l);
8386 pic16_aopPut(AOP(result),"a",offset);
8388 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8389 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8390 //pic16_aopPut(AOP(result),l,offset);
8396 size = AOP_SIZE(result);
8398 /* if it is only one byte then */
8400 if(optimized_for_speed) {
8401 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8402 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8403 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
8404 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8405 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8406 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
8407 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8408 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
8409 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
8410 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
8411 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
8412 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8415 tlbl = newiTempLabel(NULL);
8416 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8417 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8418 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8421 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8422 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8423 pic16_emitpLabel(tlbl->key);
8424 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8425 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8427 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8432 if (pic16_sameRegs(AOP(left),AOP(result))) {
8434 tlbl = newiTempLabel(NULL);
8435 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8436 genMultiAsm(POC_RRCF, result, size,1);
8437 pic16_emitpLabel(tlbl->key);
8438 genMultiAsm(POC_RLCF, result, size,0);
8439 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8441 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8445 //tlbl = newiTempLabel(NULL);
8447 //tlbl1 = newiTempLabel(NULL);
8449 //reAdjustPreg(AOP(result));
8451 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8452 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8453 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8455 //pic16_emitcode("add","a,acc");
8456 //pic16_aopPut(AOP(result),"a",offset++);
8458 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8460 // pic16_emitcode("rlc","a");
8461 // pic16_aopPut(AOP(result),"a",offset++);
8463 //reAdjustPreg(AOP(result));
8465 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8466 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8469 tlbl = newiTempLabel(NULL);
8470 tlbl1= newiTempLabel(NULL);
8472 size = AOP_SIZE(result);
8475 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8477 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8479 /* offset should be 0, 1 or 3 */
8481 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8483 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8485 pic16_emitpcode(POC_MOVWF, pctemp);
8488 pic16_emitpLabel(tlbl->key);
8491 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8493 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
8495 pic16_emitpcode(POC_DECFSZ, pctemp);
8496 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8497 pic16_emitpLabel(tlbl1->key);
8499 pic16_popReleaseTempReg(pctemp);
8503 pic16_freeAsmop (right,NULL,ic,TRUE);
8504 pic16_freeAsmop(left,NULL,ic,TRUE);
8505 pic16_freeAsmop(result,NULL,ic,TRUE);
8508 /*-----------------------------------------------------------------*/
8509 /* genrshOne - right shift a one byte quantity by known count */
8510 /*-----------------------------------------------------------------*/
8511 static void genrshOne (operand *result, operand *left,
8512 int shCount, int sign)
8514 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8515 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8518 /*-----------------------------------------------------------------*/
8519 /* genrshTwo - right shift two bytes by known amount != 0 */
8520 /*-----------------------------------------------------------------*/
8521 static void genrshTwo (operand *result,operand *left,
8522 int shCount, int sign)
8524 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8525 /* if shCount >= 8 */
8529 shiftR1Left2Result(left, MSB16, result, LSB,
8532 movLeft2Result(left, MSB16, result, LSB);
8534 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8537 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8538 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8542 /* 1 <= shCount <= 7 */
8544 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
8547 /*-----------------------------------------------------------------*/
8548 /* shiftRLong - shift right one long from left to result */
8549 /* offl = LSB or MSB16 */
8550 /*-----------------------------------------------------------------*/
8551 static void shiftRLong (operand *left, int offl,
8552 operand *result, int sign)
8554 int size = AOP_SIZE(result);
8555 int same = pic16_sameRegs(AOP(left),AOP(result));
8557 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8559 if (same && (offl == MSB16)) { //shift one byte right
8560 for(i=MSB16;i<size;i++) {
8561 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8562 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8567 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8573 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8575 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8576 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8580 /* add sign of "a" */
8581 pic16_addSign(result, MSB32, sign);
8585 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8587 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8588 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8592 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8594 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8595 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8599 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8602 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8603 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8608 /*-----------------------------------------------------------------*/
8609 /* genrshFour - shift four byte by a known amount != 0 */
8610 /*-----------------------------------------------------------------*/
8611 static void genrshFour (operand *result, operand *left,
8612 int shCount, int sign)
8614 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8615 /* if shifting more that 3 bytes */
8616 if(shCount >= 24 ) {
8619 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8621 movLeft2Result(left, MSB32, result, LSB);
8623 pic16_addSign(result, MSB16, sign);
8625 else if(shCount >= 16){
8628 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8630 movLeft2Result(left, MSB24, result, LSB);
8631 movLeft2Result(left, MSB32, result, MSB16);
8633 pic16_addSign(result, MSB24, sign);
8635 else if(shCount >= 8){
8638 shiftRLong(left, MSB16, result, sign);
8639 else if(shCount == 0){
8640 movLeft2Result(left, MSB16, result, LSB);
8641 movLeft2Result(left, MSB24, result, MSB16);
8642 movLeft2Result(left, MSB32, result, MSB24);
8643 pic16_addSign(result, MSB32, sign);
8645 else{ //shcount >= 2
8646 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8647 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8648 /* the last shift is signed */
8649 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8650 pic16_addSign(result, MSB32, sign);
8653 else{ /* 1 <= shCount <= 7 */
8655 shiftRLong(left, LSB, result, sign);
8657 shiftRLong(result, LSB, result, sign);
8660 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8661 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8662 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8667 /*-----------------------------------------------------------------*/
8668 /* genRightShiftLiteral - right shifting by known count */
8669 /*-----------------------------------------------------------------*/
8670 static void genRightShiftLiteral (operand *left,
8676 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8679 pic16_freeAsmop(right,NULL,ic,TRUE);
8681 pic16_aopOp(left,ic,FALSE);
8682 pic16_aopOp(result,ic,FALSE);
8684 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8687 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8691 lsize = pic16_getDataSize(left);
8692 res_size = pic16_getDataSize(result);
8693 /* test the LEFT size !!! */
8695 /* I suppose that the left size >= result size */
8698 movLeft2Result(left, lsize, result, res_size);
8701 else if(shCount >= (lsize * 8)){
8704 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8706 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8707 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8712 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8713 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8714 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8716 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8721 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8728 genrshOne (result,left,shCount,sign);
8732 genrshTwo (result,left,shCount,sign);
8736 genrshFour (result,left,shCount,sign);
8744 pic16_freeAsmop(left,NULL,ic,TRUE);
8745 pic16_freeAsmop(result,NULL,ic,TRUE);
8748 /*-----------------------------------------------------------------*/
8749 /* genSignedRightShift - right shift of signed number */
8750 /*-----------------------------------------------------------------*/
8751 static void genSignedRightShift (iCode *ic)
8753 operand *right, *left, *result;
8756 symbol *tlbl, *tlbl1 ;
8759 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8761 /* we do it the hard way put the shift count in b
8762 and loop thru preserving the sign */
8763 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8765 right = IC_RIGHT(ic);
8767 result = IC_RESULT(ic);
8769 pic16_aopOp(right,ic,FALSE);
8770 pic16_aopOp(left,ic,FALSE);
8771 pic16_aopOp(result,ic,FALSE);
8774 if ( AOP_TYPE(right) == AOP_LIT) {
8775 genRightShiftLiteral (left,right,result,ic,1);
8778 /* shift count is unknown then we have to form
8779 a loop get the loop count in B : Note: we take
8780 only the lower order byte since shifting
8781 more that 32 bits make no sense anyway, ( the
8782 largest size of an object can be only 32 bits ) */
8784 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8785 //pic16_emitcode("inc","b");
8786 //pic16_freeAsmop (right,NULL,ic,TRUE);
8787 //pic16_aopOp(left,ic,FALSE);
8788 //pic16_aopOp(result,ic,FALSE);
8790 /* now move the left to the result if they are not the
8792 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8793 AOP_SIZE(result) > 1) {
8795 size = AOP_SIZE(result);
8799 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8800 if (*l == '@' && IS_AOP_PREG(result)) {
8802 pic16_emitcode("mov","a,%s",l);
8803 pic16_aopPut(AOP(result),"a",offset);
8805 pic16_aopPut(AOP(result),l,offset);
8807 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8808 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8814 /* mov the highest order bit to OVR */
8815 tlbl = newiTempLabel(NULL);
8816 tlbl1= newiTempLabel(NULL);
8818 size = AOP_SIZE(result);
8821 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8823 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8825 /* offset should be 0, 1 or 3 */
8826 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8828 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8830 pic16_emitpcode(POC_MOVWF, pctemp);
8833 pic16_emitpLabel(tlbl->key);
8835 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
8836 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
8839 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
8842 pic16_emitpcode(POC_DECFSZ, pctemp);
8843 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8844 pic16_emitpLabel(tlbl1->key);
8846 pic16_popReleaseTempReg(pctemp);
8848 size = AOP_SIZE(result);
8850 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8851 pic16_emitcode("rlc","a");
8852 pic16_emitcode("mov","ov,c");
8853 /* if it is only one byte then */
8855 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8857 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8858 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8859 pic16_emitcode("mov","c,ov");
8860 pic16_emitcode("rrc","a");
8861 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8862 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8863 pic16_aopPut(AOP(result),"a",0);
8867 reAdjustPreg(AOP(result));
8868 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8869 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8870 pic16_emitcode("mov","c,ov");
8872 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8874 pic16_emitcode("rrc","a");
8875 pic16_aopPut(AOP(result),"a",offset--);
8877 reAdjustPreg(AOP(result));
8878 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8879 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8884 pic16_freeAsmop(left,NULL,ic,TRUE);
8885 pic16_freeAsmop(result,NULL,ic,TRUE);
8886 pic16_freeAsmop(right,NULL,ic,TRUE);
8889 /*-----------------------------------------------------------------*/
8890 /* genRightShift - generate code for right shifting */
8891 /*-----------------------------------------------------------------*/
8892 static void genRightShift (iCode *ic)
8894 operand *right, *left, *result;
8898 symbol *tlbl, *tlbl1 ;
8900 /* if signed then we do it the hard way preserve the
8901 sign bit moving it inwards */
8902 letype = getSpec(operandType(IC_LEFT(ic)));
8903 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8905 if (!SPEC_USIGN(letype)) {
8906 genSignedRightShift (ic);
8910 /* signed & unsigned types are treated the same : i.e. the
8911 signed is NOT propagated inwards : quoting from the
8912 ANSI - standard : "for E1 >> E2, is equivalent to division
8913 by 2**E2 if unsigned or if it has a non-negative value,
8914 otherwise the result is implementation defined ", MY definition
8915 is that the sign does not get propagated */
8917 right = IC_RIGHT(ic);
8919 result = IC_RESULT(ic);
8921 pic16_aopOp(right,ic,FALSE);
8923 /* if the shift count is known then do it
8924 as efficiently as possible */
8925 if (AOP_TYPE(right) == AOP_LIT) {
8926 genRightShiftLiteral (left,right,result,ic, 0);
8930 /* shift count is unknown then we have to form
8931 a loop get the loop count in B : Note: we take
8932 only the lower order byte since shifting
8933 more that 32 bits make no sense anyway, ( the
8934 largest size of an object can be only 32 bits ) */
8936 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8937 pic16_emitcode("inc","b");
8938 pic16_aopOp(left,ic,FALSE);
8939 pic16_aopOp(result,ic,FALSE);
8941 /* now move the left to the result if they are not the
8943 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8944 AOP_SIZE(result) > 1) {
8946 size = AOP_SIZE(result);
8949 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8950 if (*l == '@' && IS_AOP_PREG(result)) {
8952 pic16_emitcode("mov","a,%s",l);
8953 pic16_aopPut(AOP(result),"a",offset);
8955 pic16_aopPut(AOP(result),l,offset);
8960 tlbl = newiTempLabel(NULL);
8961 tlbl1= newiTempLabel(NULL);
8962 size = AOP_SIZE(result);
8965 /* if it is only one byte then */
8968 tlbl = newiTempLabel(NULL);
8969 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8970 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8971 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8974 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8975 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8976 pic16_emitpLabel(tlbl->key);
8977 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8978 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8980 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8985 reAdjustPreg(AOP(result));
8986 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8987 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8990 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8992 pic16_emitcode("rrc","a");
8993 pic16_aopPut(AOP(result),"a",offset--);
8995 reAdjustPreg(AOP(result));
8997 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8998 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9001 pic16_freeAsmop(left,NULL,ic,TRUE);
9002 pic16_freeAsmop (right,NULL,ic,TRUE);
9003 pic16_freeAsmop(result,NULL,ic,TRUE);
9006 /*-----------------------------------------------------------------*/
9007 /* genUnpackBits - generates code for unpacking bits */
9008 /*-----------------------------------------------------------------*/
9009 static void genUnpackBits (operand *result, char *rname, int ptype)
9016 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9017 etype = getSpec(operandType(result));
9019 /* read the first byte */
9026 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9029 pic16_emitcode("clr","a");
9030 pic16_emitcode("movc","a","@a+dptr");
9035 /* if we have bitdisplacement then it fits */
9036 /* into this byte completely or if length is */
9037 /* less than a byte */
9038 if ((shCnt = SPEC_BSTR(etype)) ||
9039 (SPEC_BLEN(etype) <= 8)) {
9041 /* shift right acc */
9044 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9045 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9047 /* VR -- normally I would use the following, but since we use the hack,
9048 * to avoid the masking from AccRsh, why not mask it right now? */
9051 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9054 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9060 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9061 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9064 /* bit field did not fit in a byte */
9065 rlen = SPEC_BLEN(etype) - 8;
9066 pic16_aopPut(AOP(result),"a",offset++);
9073 pic16_emitcode("inc","%s",rname);
9074 pic16_emitcode("mov","a,@%s",rname);
9078 pic16_emitcode("inc","%s",rname);
9079 pic16_emitcode("movx","a,@%s",rname);
9083 pic16_emitcode("inc","dptr");
9084 pic16_emitcode("movx","a,@dptr");
9088 pic16_emitcode("clr","a");
9089 pic16_emitcode("inc","dptr");
9090 pic16_emitcode("movc","a","@a+dptr");
9094 pic16_emitcode("inc","dptr");
9095 pic16_emitcode("lcall","__gptrget");
9100 /* if we are done */
9104 pic16_aopPut(AOP(result),"a",offset++);
9109 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9110 pic16_aopPut(AOP(result),"a",offset);
9117 static void genDataPointerGet(operand *left,
9121 int size, offset = 0, leoffset=0 ;
9123 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9124 pic16_aopOp(result, ic, FALSE);
9126 size = AOP_SIZE(result);
9127 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9131 /* The following tests may save a redudant movff instruction when
9132 * accessing unions */
9134 /* if they are the same */
9135 if (operandsEqu (left, result)) {
9136 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9142 /* if they are the same registers */
9143 if (pic16_sameRegs(AOP(left),AOP(result))) {
9144 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9150 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9151 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9152 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9159 if ( AOP_TYPE(left) == AOP_PCODE) {
9160 fprintf(stderr,"genDataPointerGet %s, %d\n",
9161 AOP(left)->aopu.pcop->name,
9162 (AOP(left)->aopu.pcop->type == PO_DIR)?
9163 PCOR(AOP(left)->aopu.pcop)->instance:
9164 PCOI(AOP(left)->aopu.pcop)->offset);
9168 if(AOP(left)->aopu.pcop->type == PO_DIR)
9169 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9171 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9174 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9176 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9177 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9178 mov2w(AOP(left), offset); // patch 8
9179 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9181 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9182 pic16_popGet(AOP(left), offset), //patch 8
9183 pic16_popGet(AOP(result), offset)));
9191 pic16_freeAsmop(result,NULL,ic,TRUE);
9194 void pic16_loadFSR0(operand *op)
9196 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9200 /*-----------------------------------------------------------------*/
9201 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
9202 /*-----------------------------------------------------------------*/
9203 static void genNearPointerGet (operand *left,
9208 //regs *preg = NULL ;
9209 sym_link *rtype, *retype;
9210 sym_link *ltype = operandType(left);
9212 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9213 rtype = operandType(result);
9214 retype= getSpec(rtype);
9216 pic16_aopOp(left,ic,FALSE);
9218 // pic16_DumpOp("(left)",left);
9219 // pic16_DumpOp("(result)",result);
9221 /* if left is rematerialisable and
9222 * result is not bit variable type and
9223 * the left is pointer to data space i.e
9224 * lower 128 bytes of space */
9225 if (AOP_TYPE(left) == AOP_PCODE
9226 && !IS_BITFIELD(retype)
9227 && DCL_TYPE(ltype) == POINTER) {
9229 genDataPointerGet (left,result,ic);
9230 pic16_freeAsmop(left, NULL, ic, TRUE);
9234 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9236 /* if the value is already in a pointer register
9237 * then don't need anything more */
9238 if (!AOP_INPREG(AOP(left))) {
9239 /* otherwise get a free pointer register */
9240 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9242 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9243 if( (AOP_TYPE(left) == AOP_PCODE)
9244 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9245 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9247 pic16_loadFSR0( left ); // patch 10
9249 // set up FSR0 with address from left
9250 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9251 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9255 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9257 pic16_aopOp (result,ic,FALSE);
9259 /* if bitfield then unpack the bits */
9260 if (IS_BITFIELD(retype))
9261 genUnpackBits (result, NULL, POINTER);
9263 /* we have can just get the values */
9264 int size = AOP_SIZE(result);
9267 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9270 /* fsr0 is loaded already -- VR */
9271 // pic16_loadFSR0( left );
9273 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9274 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9278 pic16_emitpcode(POC_MOVFF,
9279 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9280 pic16_popGet(AOP(result), offset++)));
9282 pic16_emitpcode(POC_MOVFF,
9283 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9284 pic16_popGet(AOP(result), offset++)));
9288 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9289 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9291 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9295 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9297 pic16_emitcode("mov","a,@%s",rname);
9298 pic16_aopPut(AOP(result),"a",offset);
9300 sprintf(buffer,"@%s",rname);
9301 pic16_aopPut(AOP(result),buffer,offset);
9305 pic16_emitcode("inc","%s",rname);
9310 /* now some housekeeping stuff */
9312 /* we had to allocate for this iCode */
9313 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9314 pic16_freeAsmop(NULL,aop,ic,TRUE);
9316 /* we did not allocate which means left
9317 already in a pointer register, then
9318 if size > 0 && this could be used again
9319 we have to point it back to where it
9321 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9322 if (AOP_SIZE(result) > 1 &&
9323 !OP_SYMBOL(left)->remat &&
9324 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9326 // int size = AOP_SIZE(result) - 1;
9328 // pic16_emitcode("dec","%s",rname);
9333 pic16_freeAsmop(left,NULL,ic,TRUE);
9334 pic16_freeAsmop(result,NULL,ic,TRUE);
9338 /*-----------------------------------------------------------------*/
9339 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
9340 /*-----------------------------------------------------------------*/
9341 static void genPagedPointerGet (operand *left,
9348 sym_link *rtype, *retype;
9350 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9352 rtype = operandType(result);
9353 retype= getSpec(rtype);
9355 pic16_aopOp(left,ic,FALSE);
9357 /* if the value is already in a pointer register
9358 then don't need anything more */
9359 if (!AOP_INPREG(AOP(left))) {
9360 /* otherwise get a free pointer register */
9362 preg = getFreePtr(ic,&aop,FALSE);
9363 pic16_emitcode("mov","%s,%s",
9365 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9366 rname = preg->name ;
9368 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9370 pic16_freeAsmop(left,NULL,ic,TRUE);
9371 pic16_aopOp (result,ic,FALSE);
9373 /* if bitfield then unpack the bits */
9374 if (IS_BITFIELD(retype))
9375 genUnpackBits (result,rname,PPOINTER);
9377 /* we have can just get the values */
9378 int size = AOP_SIZE(result);
9383 pic16_emitcode("movx","a,@%s",rname);
9384 pic16_aopPut(AOP(result),"a",offset);
9389 pic16_emitcode("inc","%s",rname);
9393 /* now some housekeeping stuff */
9395 /* we had to allocate for this iCode */
9396 pic16_freeAsmop(NULL,aop,ic,TRUE);
9398 /* we did not allocate which means left
9399 already in a pointer register, then
9400 if size > 0 && this could be used again
9401 we have to point it back to where it
9403 if (AOP_SIZE(result) > 1 &&
9404 !OP_SYMBOL(left)->remat &&
9405 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9407 int size = AOP_SIZE(result) - 1;
9409 pic16_emitcode("dec","%s",rname);
9414 pic16_freeAsmop(result,NULL,ic,TRUE);
9419 /*-----------------------------------------------------------------*/
9420 /* genFarPointerGet - gget value from far space */
9421 /*-----------------------------------------------------------------*/
9422 static void genFarPointerGet (operand *left,
9423 operand *result, iCode *ic)
9426 sym_link *retype = getSpec(operandType(result));
9428 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9430 pic16_aopOp(left,ic,FALSE);
9432 /* if the operand is already in dptr
9433 then we do nothing else we move the value to dptr */
9434 if (AOP_TYPE(left) != AOP_STR) {
9435 /* if this is remateriazable */
9436 if (AOP_TYPE(left) == AOP_IMMD)
9437 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9438 else { /* we need to get it byte by byte */
9439 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9440 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9441 if (options.model == MODEL_FLAT24)
9443 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9447 /* so dptr know contains the address */
9448 pic16_freeAsmop(left,NULL,ic,TRUE);
9449 pic16_aopOp(result,ic,FALSE);
9451 /* if bit then unpack */
9452 if (IS_BITFIELD(retype))
9453 genUnpackBits(result,"dptr",FPOINTER);
9455 size = AOP_SIZE(result);
9459 pic16_emitcode("movx","a,@dptr");
9460 pic16_aopPut(AOP(result),"a",offset++);
9462 pic16_emitcode("inc","dptr");
9466 pic16_freeAsmop(result,NULL,ic,TRUE);
9469 /*-----------------------------------------------------------------*/
9470 /* genCodePointerGet - get value from code space */
9471 /*-----------------------------------------------------------------*/
9472 static void genCodePointerGet (operand *left,
9473 operand *result, iCode *ic)
9476 sym_link *retype = getSpec(operandType(result));
9478 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9480 pic16_aopOp(left,ic,FALSE);
9482 /* if the operand is already in dptr
9483 then we do nothing else we move the value to dptr */
9484 if (AOP_TYPE(left) != AOP_STR) {
9485 /* if this is remateriazable */
9486 if (AOP_TYPE(left) == AOP_IMMD)
9487 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9488 else { /* we need to get it byte by byte */
9489 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9490 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9491 if (options.model == MODEL_FLAT24)
9493 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9497 /* so dptr know contains the address */
9498 pic16_freeAsmop(left,NULL,ic,TRUE);
9499 pic16_aopOp(result,ic,FALSE);
9501 /* if bit then unpack */
9502 if (IS_BITFIELD(retype))
9503 genUnpackBits(result,"dptr",CPOINTER);
9505 size = AOP_SIZE(result);
9509 pic16_emitcode("clr","a");
9510 pic16_emitcode("movc","a,@a+dptr");
9511 pic16_aopPut(AOP(result),"a",offset++);
9513 pic16_emitcode("inc","dptr");
9517 pic16_freeAsmop(result,NULL,ic,TRUE);
9520 /*-----------------------------------------------------------------*/
9521 /* genGenPointerGet - gget value from generic pointer space */
9522 /*-----------------------------------------------------------------*/
9523 static void genGenPointerGet (operand *left,
9524 operand *result, iCode *ic)
9526 int size, offset, lit;
9527 sym_link *retype = getSpec(operandType(result));
9529 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9530 pic16_aopOp(left,ic,FALSE);
9531 pic16_aopOp(result,ic,FALSE);
9532 size = AOP_SIZE(result);
9534 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9536 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9538 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9539 // load FSR0 from immediate
9540 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9542 // pic16_loadFSR0( left );
9547 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9549 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9556 else { /* we need to get it byte by byte */
9557 // set up FSR0 with address from left
9558 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9559 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9565 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9567 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9574 /* if bit then unpack */
9575 if (IS_BITFIELD(retype))
9576 genUnpackBits(result,"BAD",GPOINTER);
9579 pic16_freeAsmop(left,NULL,ic,TRUE);
9580 pic16_freeAsmop(result,NULL,ic,TRUE);
9584 /*-----------------------------------------------------------------*/
9585 /* genConstPointerGet - get value from const generic pointer space */
9586 /*-----------------------------------------------------------------*/
9587 static void genConstPointerGet (operand *left,
9588 operand *result, iCode *ic)
9590 //sym_link *retype = getSpec(operandType(result));
9591 // symbol *albl = newiTempLabel(NULL); // patch 15
9592 // symbol *blbl = newiTempLabel(NULL); //
9593 // PIC_OPCODE poc; // patch 15
9597 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9598 pic16_aopOp(left,ic,FALSE);
9599 pic16_aopOp(result,ic,TRUE);
9600 size = AOP_SIZE(result);
9602 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9604 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9606 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9607 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9608 pic16_emitpLabel(albl->key);
9610 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9612 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9613 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9614 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9615 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9616 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9618 pic16_emitpLabel(blbl->key);
9620 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9624 // set up table pointer
9625 if( (AOP_TYPE(left) == AOP_PCODE)
9626 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9627 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
9629 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9630 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9631 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9632 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9633 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9634 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9638 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9639 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9640 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9646 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9647 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9651 pic16_freeAsmop(left,NULL,ic,TRUE);
9652 pic16_freeAsmop(result,NULL,ic,TRUE);
9657 /*-----------------------------------------------------------------*/
9658 /* genPointerGet - generate code for pointer get */
9659 /*-----------------------------------------------------------------*/
9660 static void genPointerGet (iCode *ic)
9662 operand *left, *result ;
9663 sym_link *type, *etype;
9666 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9669 result = IC_RESULT(ic) ;
9671 /* depending on the type of pointer we need to
9672 move it to the correct pointer register */
9673 type = operandType(left);
9674 etype = getSpec(type);
9677 if (IS_PTR_CONST(type))
9679 if (IS_CODEPTR(type))
9681 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9683 /* if left is of type of pointer then it is simple */
9684 if (IS_PTR(type) && !IS_FUNC(type->next))
9685 p_type = DCL_TYPE(type);
9687 /* we have to go by the storage class */
9688 p_type = PTR_TYPE(SPEC_OCLS(etype));
9690 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9692 if (SPEC_OCLS(etype)->codesp ) {
9693 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9694 //p_type = CPOINTER ;
9697 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9698 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9699 /*p_type = FPOINTER ;*/
9701 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9702 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9703 /* p_type = PPOINTER; */
9705 if (SPEC_OCLS(etype) == idata )
9706 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9707 /* p_type = IPOINTER; */
9709 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9710 /* p_type = POINTER ; */
9713 /* now that we have the pointer type we assign
9714 the pointer values */
9719 genNearPointerGet (left,result,ic);
9723 genPagedPointerGet(left,result,ic);
9727 genFarPointerGet (left,result,ic);
9731 genConstPointerGet (left,result,ic);
9732 //pic16_emitcodePointerGet (left,result,ic);
9737 if (IS_PTR_CONST(type))
9738 genConstPointerGet (left,result,ic);
9741 genGenPointerGet (left,result,ic);
9745 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9746 "genPointerGet: illegal pointer type");
9752 /*-----------------------------------------------------------------*/
9753 /* genPackBits - generates code for packed bit storage */
9754 /*-----------------------------------------------------------------*/
9755 static void genPackBits (sym_link *etype ,
9757 char *rname, int p_type)
9765 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9766 blen = SPEC_BLEN(etype);
9767 bstr = SPEC_BSTR(etype);
9769 if(AOP_TYPE(right) == AOP_LIT) {
9770 if((blen == 1) && (bstr < 8)) {
9772 /* it is a single bit, so use the appropriate bit instructions */
9774 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9776 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9777 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9779 pic16_emitpcode(POC_BSF,
9780 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9782 pic16_emitpcode(POC_BCF,
9783 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9789 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9792 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9794 /* if the bit lenth is less than or */
9795 /* it exactly fits a byte then */
9796 if((shCnt=SPEC_BSTR(etype))
9797 || SPEC_BLEN(etype) <= 8 ) {
9799 /* shift left acc */
9802 /* using PRODL as a temporary register here */
9803 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9809 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9810 // pic16_emitcode ("mov","b,a");
9811 // pic16_emitcode("mov","a,@%s",rname);
9815 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9816 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9817 (unsigned char)(0xff >> (8-bstr))) ));
9818 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9819 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9826 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9827 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9832 if ( SPEC_BLEN(etype) <= 8 )
9835 pic16_emitcode("inc","%s",rname);
9836 rLen = SPEC_BLEN(etype) ;
9840 /* now generate for lengths greater than one byte */
9843 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9853 pic16_emitcode("mov","@%s,a",rname);
9855 pic16_emitcode("mov","@%s,%s",rname,l);
9860 pic16_emitcode("movx","@dptr,a");
9865 DEBUGpic16_emitcode(";lcall","__gptrput");
9868 pic16_emitcode ("inc","%s",rname);
9873 /* last last was not complete */
9875 /* save the byte & read byte */
9878 pic16_emitcode ("mov","b,a");
9879 pic16_emitcode("mov","a,@%s",rname);
9883 pic16_emitcode ("mov","b,a");
9884 pic16_emitcode("movx","a,@dptr");
9888 pic16_emitcode ("push","b");
9889 pic16_emitcode ("push","acc");
9890 pic16_emitcode ("lcall","__gptrget");
9891 pic16_emitcode ("pop","b");
9895 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9896 pic16_emitcode ("orl","a,b");
9899 if (p_type == GPOINTER)
9900 pic16_emitcode("pop","b");
9905 pic16_emitcode("mov","@%s,a",rname);
9909 pic16_emitcode("movx","@dptr,a");
9913 DEBUGpic16_emitcode(";lcall","__gptrput");
9917 /*-----------------------------------------------------------------*/
9918 /* genDataPointerSet - remat pointer to data space */
9919 /*-----------------------------------------------------------------*/
9920 static void genDataPointerSet(operand *right,
9924 int size, offset = 0, resoffset=0 ;
9926 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9927 pic16_aopOp(right,ic,FALSE);
9929 size = AOP_SIZE(right);
9931 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9934 if ( AOP_TYPE(result) == AOP_PCODE) {
9935 fprintf(stderr,"genDataPointerSet %s, %d\n",
9936 AOP(result)->aopu.pcop->name,
9937 (AOP(result)->aopu.pcop->type == PO_DIR)?
9938 PCOR(AOP(result)->aopu.pcop)->instance:
9939 PCOI(AOP(result)->aopu.pcop)->offset);
9943 if(AOP(result)->aopu.pcop->type == PO_DIR)
9944 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9947 if (AOP_TYPE(right) == AOP_LIT) {
9948 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9950 lit = lit >> (8*offset);
9952 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9953 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9955 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9958 mov2w(AOP(right), offset);
9959 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9965 pic16_freeAsmop(right,NULL,ic,TRUE);
9970 /*-----------------------------------------------------------------*/
9971 /* genNearPointerSet - pic16_emitcode for near pointer put */
9972 /*-----------------------------------------------------------------*/
9973 static void genNearPointerSet (operand *right,
9980 sym_link *ptype = operandType(result);
9983 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9984 retype= getSpec(operandType(right));
9985 resetype = getSpec(operandType(result));
9987 pic16_aopOp(result,ic,FALSE);
9989 /* if the result is rematerializable &
9990 * in data space & not a bit variable */
9992 /* and result is not a bit variable */
9993 if (AOP_TYPE(result) == AOP_PCODE
9994 // && AOP_TYPE(result) == AOP_IMMD
9995 && DCL_TYPE(ptype) == POINTER
9996 && !IS_BITFIELD(retype)
9997 && !IS_BITFIELD(resetype)) {
9999 genDataPointerSet (right,result,ic);
10000 pic16_freeAsmop(result,NULL,ic,TRUE);
10004 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10005 pic16_aopOp(right,ic,FALSE);
10006 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10008 /* if the value is already in a pointer register
10009 * then don't need anything more */
10010 if (!AOP_INPREG(AOP(result))) {
10011 /* otherwise get a free pointer register */
10012 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10014 if( (AOP_TYPE(result) == AOP_PCODE)
10015 && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10016 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10018 pic16_loadFSR0( result ); // patch 10
10020 // set up FSR0 with address of result
10021 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10022 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10027 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10029 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10031 /* if bitfield then unpack the bits */
10032 if (IS_BITFIELD(resetype)) {
10033 genPackBits (resetype, right, NULL, POINTER);
10035 /* we have can just get the values */
10036 int size = AOP_SIZE(right);
10039 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10041 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10044 //pic16_emitcode("mov","@%s,a",rname);
10045 pic16_emitcode("movf","indf0,w ;1");
10048 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
10049 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
10051 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
10053 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
10055 } else { // no literal //
10057 pic16_emitpcode(POC_MOVFF, //
10058 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10059 pic16_popCopyReg(&pic16_pc_postinc0))); //
10061 pic16_emitpcode(POC_MOVFF, //
10062 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10063 pic16_popCopyReg(&pic16_pc_indf0))); //
10071 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10072 /* now some housekeeping stuff */
10074 /* we had to allocate for this iCode */
10075 pic16_freeAsmop(NULL,aop,ic,TRUE);
10077 /* we did not allocate which means left
10078 * already in a pointer register, then
10079 * if size > 0 && this could be used again
10080 * we have to point it back to where it
10082 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10083 if (AOP_SIZE(right) > 1
10084 && !OP_SYMBOL(result)->remat
10085 && ( OP_SYMBOL(result)->liveTo > ic->seq
10088 int size = AOP_SIZE(right) - 1;
10091 pic16_emitcode("decf","fsr0,f");
10092 //pic16_emitcode("dec","%s",rname);
10096 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10099 pic16_freeAsmop(right,NULL,ic,TRUE);
10100 pic16_freeAsmop(result,NULL,ic,TRUE);
10103 /*-----------------------------------------------------------------*/
10104 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
10105 /*-----------------------------------------------------------------*/
10106 static void genPagedPointerSet (operand *right,
10111 regs *preg = NULL ;
10115 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10117 retype= getSpec(operandType(right));
10119 pic16_aopOp(result,ic,FALSE);
10121 /* if the value is already in a pointer register
10122 then don't need anything more */
10123 if (!AOP_INPREG(AOP(result))) {
10124 /* otherwise get a free pointer register */
10126 preg = getFreePtr(ic,&aop,FALSE);
10127 pic16_emitcode("mov","%s,%s",
10129 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10130 rname = preg->name ;
10132 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10134 pic16_freeAsmop(result,NULL,ic,TRUE);
10135 pic16_aopOp (right,ic,FALSE);
10137 /* if bitfield then unpack the bits */
10138 if (IS_BITFIELD(retype))
10139 genPackBits (retype,right,rname,PPOINTER);
10141 /* we have can just get the values */
10142 int size = AOP_SIZE(right);
10146 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10149 pic16_emitcode("movx","@%s,a",rname);
10152 pic16_emitcode("inc","%s",rname);
10158 /* now some housekeeping stuff */
10160 /* we had to allocate for this iCode */
10161 pic16_freeAsmop(NULL,aop,ic,TRUE);
10163 /* we did not allocate which means left
10164 already in a pointer register, then
10165 if size > 0 && this could be used again
10166 we have to point it back to where it
10168 if (AOP_SIZE(right) > 1 &&
10169 !OP_SYMBOL(result)->remat &&
10170 ( OP_SYMBOL(result)->liveTo > ic->seq ||
10172 int size = AOP_SIZE(right) - 1;
10174 pic16_emitcode("dec","%s",rname);
10179 pic16_freeAsmop(right,NULL,ic,TRUE);
10184 /*-----------------------------------------------------------------*/
10185 /* genFarPointerSet - set value from far space */
10186 /*-----------------------------------------------------------------*/
10187 static void genFarPointerSet (operand *right,
10188 operand *result, iCode *ic)
10191 sym_link *retype = getSpec(operandType(right));
10193 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10194 pic16_aopOp(result,ic,FALSE);
10196 /* if the operand is already in dptr
10197 then we do nothing else we move the value to dptr */
10198 if (AOP_TYPE(result) != AOP_STR) {
10199 /* if this is remateriazable */
10200 if (AOP_TYPE(result) == AOP_IMMD)
10201 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10202 else { /* we need to get it byte by byte */
10203 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10204 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10205 if (options.model == MODEL_FLAT24)
10207 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10211 /* so dptr know contains the address */
10212 pic16_freeAsmop(result,NULL,ic,TRUE);
10213 pic16_aopOp(right,ic,FALSE);
10215 /* if bit then unpack */
10216 if (IS_BITFIELD(retype))
10217 genPackBits(retype,right,"dptr",FPOINTER);
10219 size = AOP_SIZE(right);
10223 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10225 pic16_emitcode("movx","@dptr,a");
10227 pic16_emitcode("inc","dptr");
10231 pic16_freeAsmop(right,NULL,ic,TRUE);
10234 /*-----------------------------------------------------------------*/
10235 /* genGenPointerSet - set value from generic pointer space */
10236 /*-----------------------------------------------------------------*/
10237 static void genGenPointerSet (operand *right,
10238 operand *result, iCode *ic)
10240 int i, size, offset, lit;
10241 sym_link *retype = getSpec(operandType(right));
10243 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10245 pic16_aopOp(result,ic,FALSE);
10246 pic16_aopOp(right,ic,FALSE);
10247 size = AOP_SIZE(right);
10250 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10252 /* if the operand is already in dptr
10253 then we do nothing else we move the value to dptr */
10254 if (AOP_TYPE(result) != AOP_STR) {
10255 /* if this is remateriazable */
10256 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10257 // WARNING: anythig until "else" is untested!
10258 if (AOP_TYPE(result) == AOP_IMMD) {
10259 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10260 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10261 // load FSR0 from immediate
10262 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10266 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10268 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10274 else { /* we need to get it byte by byte */
10275 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10276 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10278 // set up FSR0 with address of result
10279 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10280 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10282 /* hack hack! see if this the FSR. If so don't load W */
10283 if(AOP_TYPE(right) != AOP_ACC) {
10285 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10287 if(AOP_TYPE(right) == AOP_LIT)
10290 // note: pic16_popGet handles sign extension
10291 for(i=0;i<size;i++) {
10292 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10294 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10296 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10301 for(i=0;i<size;i++) {
10303 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10304 pic16_popCopyReg(&pic16_pc_postinc0)));
10306 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10307 pic16_popCopyReg(&pic16_pc_indf0)));
10313 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10314 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10316 } // if (AOP_TYPE(result) != AOP_IMMD)
10318 } // if (AOP_TYPE(result) != AOP_STR)
10319 /* so dptr know contains the address */
10322 /* if bit then unpack */
10323 if (IS_BITFIELD(retype))
10324 genPackBits(retype,right,"dptr",GPOINTER);
10326 size = AOP_SIZE(right);
10329 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
10331 // set up FSR0 with address of result
10332 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10333 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10336 if (AOP_TYPE(right) == AOP_LIT) {
10337 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10339 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10341 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10343 } else { // no literal
10345 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10347 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10355 pic16_freeAsmop(right,NULL,ic,TRUE);
10356 pic16_freeAsmop(result,NULL,ic,TRUE);
10359 /*-----------------------------------------------------------------*/
10360 /* genPointerSet - stores the value into a pointer location */
10361 /*-----------------------------------------------------------------*/
10362 static void genPointerSet (iCode *ic)
10364 operand *right, *result ;
10365 sym_link *type, *etype;
10368 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10370 right = IC_RIGHT(ic);
10371 result = IC_RESULT(ic) ;
10373 /* depending on the type of pointer we need to
10374 move it to the correct pointer register */
10375 type = operandType(result);
10376 etype = getSpec(type);
10377 /* if left is of type of pointer then it is simple */
10378 if (IS_PTR(type) && !IS_FUNC(type->next)) {
10379 p_type = DCL_TYPE(type);
10382 /* we have to go by the storage class */
10383 p_type = PTR_TYPE(SPEC_OCLS(etype));
10385 /* if (SPEC_OCLS(etype)->codesp ) { */
10386 /* p_type = CPOINTER ; */
10389 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10390 /* p_type = FPOINTER ; */
10392 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10393 /* p_type = PPOINTER ; */
10395 /* if (SPEC_OCLS(etype) == idata ) */
10396 /* p_type = IPOINTER ; */
10398 /* p_type = POINTER ; */
10401 /* now that we have the pointer type we assign
10402 the pointer values */
10407 genNearPointerSet (right,result,ic);
10411 genPagedPointerSet (right,result,ic);
10415 genFarPointerSet (right,result,ic);
10419 genGenPointerSet (right,result,ic);
10423 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10424 "genPointerSet: illegal pointer type");
10428 /*-----------------------------------------------------------------*/
10429 /* genIfx - generate code for Ifx statement */
10430 /*-----------------------------------------------------------------*/
10431 static void genIfx (iCode *ic, iCode *popIc)
10433 operand *cond = IC_COND(ic);
10436 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10438 pic16_aopOp(cond,ic,FALSE);
10440 /* get the value into acc */
10441 if (AOP_TYPE(cond) != AOP_CRY)
10442 pic16_toBoolean(cond);
10445 /* the result is now in the accumulator */
10446 pic16_freeAsmop(cond,NULL,ic,TRUE);
10448 /* if there was something to be popped then do it */
10452 /* if the condition is a bit variable */
10453 if (isbit && IS_ITEMP(cond) &&
10455 genIfxJump(ic,SPIL_LOC(cond)->rname);
10456 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10459 if (isbit && !IS_ITEMP(cond))
10460 genIfxJump(ic,OP_SYMBOL(cond)->rname);
10462 genIfxJump(ic,"a");
10468 /*-----------------------------------------------------------------*/
10469 /* genAddrOf - generates code for address of */
10470 /*-----------------------------------------------------------------*/
10471 static void genAddrOf (iCode *ic)
10473 operand *result, *left;
10475 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
10476 pCodeOp *pcop0, *pcop1, *pcop2;
10478 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10480 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10481 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10483 sym = OP_SYMBOL( left );
10485 size = AOP_SIZE(IC_RESULT(ic));
10487 // if(pic16_debug_verbose) {
10488 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10489 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10492 /* Assume that what we want the address of is in data space
10493 * since there is no stack on the PIC, yet! -- VR */
10495 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10498 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10501 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10505 pic16_emitpcode(POC_MOVLW, pcop0);
10506 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10507 pic16_emitpcode(POC_MOVLW, pcop1);
10508 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10509 pic16_emitpcode(POC_MOVLW, pcop2);
10510 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10513 pic16_emitpcode(POC_MOVLW, pcop0);
10514 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10515 pic16_emitpcode(POC_MOVLW, pcop1);
10516 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10518 pic16_emitpcode(POC_MOVLW, pcop0);
10519 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10522 pic16_freeAsmop(result,NULL,ic,TRUE);
10523 pic16_freeAsmop(left, NULL, ic, FALSE);
10528 /*-----------------------------------------------------------------*/
10529 /* genFarFarAssign - assignment when both are in far space */
10530 /*-----------------------------------------------------------------*/
10531 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10533 int size = AOP_SIZE(right);
10536 /* first push the right side on to the stack */
10538 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10540 pic16_emitcode ("push","acc");
10543 pic16_freeAsmop(right,NULL,ic,FALSE);
10544 /* now assign DPTR to result */
10545 pic16_aopOp(result,ic,FALSE);
10546 size = AOP_SIZE(result);
10548 pic16_emitcode ("pop","acc");
10549 pic16_aopPut(AOP(result),"a",--offset);
10551 pic16_freeAsmop(result,NULL,ic,FALSE);
10556 /*-----------------------------------------------------------------*/
10557 /* genAssign - generate code for assignment */
10558 /*-----------------------------------------------------------------*/
10559 static void genAssign (iCode *ic)
10561 operand *result, *right;
10562 int size, offset,know_W;
10563 unsigned long lit = 0L;
10565 result = IC_RESULT(ic);
10566 right = IC_RIGHT(ic) ;
10568 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10570 /* if they are the same */
10571 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10574 pic16_aopOp(right,ic,FALSE);
10575 pic16_aopOp(result,ic,TRUE);
10577 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10579 /* if they are the same registers */
10580 if (pic16_sameRegs(AOP(right),AOP(result)))
10583 /* if the result is a bit */
10584 if (AOP_TYPE(result) == AOP_CRY) {
10585 /* if the right size is a literal then
10586 we know what the value is */
10587 if (AOP_TYPE(right) == AOP_LIT) {
10589 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10590 pic16_popGet(AOP(result),0));
10592 if (((int) operandLitValue(right)))
10593 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10594 AOP(result)->aopu.aop_dir,
10595 AOP(result)->aopu.aop_dir);
10597 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10598 AOP(result)->aopu.aop_dir,
10599 AOP(result)->aopu.aop_dir);
10603 /* the right is also a bit variable */
10604 if (AOP_TYPE(right) == AOP_CRY) {
10605 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10606 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10607 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10609 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10610 AOP(result)->aopu.aop_dir,
10611 AOP(result)->aopu.aop_dir);
10612 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10613 AOP(right)->aopu.aop_dir,
10614 AOP(right)->aopu.aop_dir);
10615 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10616 AOP(result)->aopu.aop_dir,
10617 AOP(result)->aopu.aop_dir);
10621 /* we need to or */
10622 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10623 pic16_toBoolean(right);
10625 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10626 //pic16_aopPut(AOP(result),"a",0);
10630 /* bit variables done */
10632 size = AOP_SIZE(result);
10635 if(AOP_TYPE(right) == AOP_LIT) {
10636 if(!IS_FLOAT(operandType( right )))
10637 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10640 unsigned long lit_int;
10644 /* take care if literal is a float */
10645 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10646 lit = info.lit_int;
10650 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10651 // sizeof(unsigned long int), sizeof(float));
10653 if(AOP_TYPE(right) != AOP_LIT
10654 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10655 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10657 // set up table pointer
10658 if( (AOP_TYPE(right) == AOP_PCODE)
10659 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10660 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10662 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10663 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10664 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10665 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10666 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10667 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10669 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10670 pic16_popCopyReg(&pic16_pc_tblptrl)));
10671 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10672 pic16_popCopyReg(&pic16_pc_tblptrh)));
10673 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10674 pic16_popCopyReg(&pic16_pc_tblptru)));
10677 size = min(AOP_SIZE(right), AOP_SIZE(result));
10679 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10680 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10681 pic16_popGet(AOP(result),offset)));
10685 if(AOP_SIZE(result) > AOP_SIZE(right)) {
10686 size = AOP_SIZE(result) - AOP_SIZE(right);
10688 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10697 /* VR - What is this?! */
10698 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10699 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10700 if(aopIdx(AOP(result),0) == 4) {
10701 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10703 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10704 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10708 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10713 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10714 if(AOP_TYPE(right) == AOP_LIT) {
10716 if(know_W != (lit&0xff))
10717 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10719 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10721 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10725 } else if (AOP_TYPE(right) == AOP_CRY) {
10726 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10728 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10729 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10731 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10732 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10733 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10735 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10738 /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10739 normally should work, but mind that the W register live range
10740 is not checked, so if the code generator assumes that the W
10741 is already loaded after such a pair, wrong code will be generated.
10743 Checking the live range is the next step.
10744 This is experimental code yet and has not been fully tested yet.
10745 USE WITH CARE. Revert to old code by setting 0 to the condition above.
10746 Vangelis Rokas 030603 (vrokas@otenet.gr) */
10748 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10750 /* This is the old code, which is assumed(?!) that works fine(!?) */
10752 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10753 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10762 pic16_freeAsmop (right,NULL,ic,FALSE);
10763 pic16_freeAsmop (result,NULL,ic,TRUE);
10766 /*-----------------------------------------------------------------*/
10767 /* genJumpTab - generates code for jump table */
10768 /*-----------------------------------------------------------------*/
10769 static void genJumpTab (iCode *ic)
10774 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10776 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10777 /* get the condition into accumulator */
10778 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10780 /* multiply by three */
10781 pic16_emitcode("add","a,acc");
10782 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10784 jtab = newiTempLabel(NULL);
10785 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10786 pic16_emitcode("jmp","@a+dptr");
10787 pic16_emitcode("","%05d_DS_:",jtab->key+100);
10789 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10790 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10792 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10793 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10794 pic16_emitpLabel(jtab->key);
10796 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10798 /* now generate the jump labels */
10799 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10800 jtab = setNextItem(IC_JTLABELS(ic))) {
10801 pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10802 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10808 /*-----------------------------------------------------------------*/
10809 /* genMixedOperation - gen code for operators between mixed types */
10810 /*-----------------------------------------------------------------*/
10812 TSD - Written for the PIC port - but this unfortunately is buggy.
10813 This routine is good in that it is able to efficiently promote
10814 types to different (larger) sizes. Unfortunately, the temporary
10815 variables that are optimized out by this routine are sometimes
10816 used in other places. So until I know how to really parse the
10817 iCode tree, I'm going to not be using this routine :(.
10819 static int genMixedOperation (iCode *ic)
10822 operand *result = IC_RESULT(ic);
10823 sym_link *ctype = operandType(IC_LEFT(ic));
10824 operand *right = IC_RIGHT(ic);
10830 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10832 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10838 nextright = IC_RIGHT(nextic);
10839 nextleft = IC_LEFT(nextic);
10840 nextresult = IC_RESULT(nextic);
10842 pic16_aopOp(right,ic,FALSE);
10843 pic16_aopOp(result,ic,FALSE);
10844 pic16_aopOp(nextright, nextic, FALSE);
10845 pic16_aopOp(nextleft, nextic, FALSE);
10846 pic16_aopOp(nextresult, nextic, FALSE);
10848 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10850 operand *t = right;
10854 pic16_emitcode(";remove right +","");
10856 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10858 operand *t = right;
10862 pic16_emitcode(";remove left +","");
10866 big = AOP_SIZE(nextleft);
10867 small = AOP_SIZE(nextright);
10869 switch(nextic->op) {
10872 pic16_emitcode(";optimize a +","");
10873 /* if unsigned or not an integral type */
10874 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10875 pic16_emitcode(";add a bit to something","");
10878 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10880 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10881 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10882 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10884 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10892 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10893 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10894 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10897 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10899 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10900 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10901 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10902 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10903 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10906 pic16_emitcode("rlf","known_zero,w");
10913 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10914 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10915 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10917 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10927 pic16_freeAsmop(right,NULL,ic,TRUE);
10928 pic16_freeAsmop(result,NULL,ic,TRUE);
10929 pic16_freeAsmop(nextright,NULL,ic,TRUE);
10930 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10932 nextic->generated = 1;
10939 /*-----------------------------------------------------------------*/
10940 /* genCast - gen code for casting */
10941 /*-----------------------------------------------------------------*/
10942 static void genCast (iCode *ic)
10944 operand *result = IC_RESULT(ic);
10945 sym_link *ctype = operandType(IC_LEFT(ic));
10946 sym_link *rtype = operandType(IC_RIGHT(ic));
10947 operand *right = IC_RIGHT(ic);
10950 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10951 /* if they are equivalent then do nothing */
10952 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10955 pic16_aopOp(right,ic,FALSE) ;
10956 pic16_aopOp(result,ic,FALSE);
10958 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10960 /* if the result is a bit */
10961 if (AOP_TYPE(result) == AOP_CRY) {
10963 /* if the right size is a literal then
10964 * we know what the value is */
10965 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10967 if (AOP_TYPE(right) == AOP_LIT) {
10968 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10969 pic16_popGet(AOP(result),0));
10971 if (((int) operandLitValue(right)))
10972 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10973 AOP(result)->aopu.aop_dir,
10974 AOP(result)->aopu.aop_dir);
10976 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10977 AOP(result)->aopu.aop_dir,
10978 AOP(result)->aopu.aop_dir);
10982 /* the right is also a bit variable */
10983 if (AOP_TYPE(right) == AOP_CRY) {
10985 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10987 pic16_emitcode("clrc","");
10988 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10989 AOP(right)->aopu.aop_dir,
10990 AOP(right)->aopu.aop_dir);
10991 pic16_aopPut(AOP(result),"c",0);
10995 /* we need to or */
10996 if (AOP_TYPE(right) == AOP_REG) {
10997 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10998 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10999 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
11001 pic16_toBoolean(right);
11002 pic16_aopPut(AOP(result),"a",0);
11006 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11009 size = AOP_SIZE(result);
11011 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11013 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
11014 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11015 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
11018 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11023 /* if they are the same size : or less */
11024 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11026 /* if they are in the same place */
11027 if (pic16_sameRegs(AOP(right),AOP(result)))
11030 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11032 if (IS_PTR_CONST(rtype))
11034 if (IS_CODEPTR(rtype))
11036 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11039 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11041 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11043 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11046 if(AOP_TYPE(right) == AOP_IMMD) {
11047 pCodeOp *pcop0, *pcop1, *pcop2;
11048 symbol *sym = OP_SYMBOL( right );
11050 size = AOP_SIZE(result);
11052 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11054 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11056 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11059 pic16_emitpcode(POC_MOVLW, pcop0);
11060 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11061 pic16_emitpcode(POC_MOVLW, pcop1);
11062 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11063 pic16_emitpcode(POC_MOVLW, pcop2);
11064 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11067 pic16_emitpcode(POC_MOVLW, pcop0);
11068 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11069 pic16_emitpcode(POC_MOVLW, pcop1);
11070 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11072 pic16_emitpcode(POC_MOVLW, pcop0);
11073 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11077 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11078 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11079 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11080 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11081 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11082 if(AOP_SIZE(result) <2)
11083 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11085 /* if they in different places then copy */
11086 size = AOP_SIZE(result);
11089 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11090 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11097 /* if the result is of type pointer */
11098 if (IS_PTR(ctype)) {
11100 sym_link *type = operandType(right);
11101 sym_link *etype = getSpec(type);
11103 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
11105 /* pointer to generic pointer */
11106 if (IS_GENPTR(ctype)) {
11110 p_type = DCL_TYPE(type);
11112 /* we have to go by the storage class */
11113 p_type = PTR_TYPE(SPEC_OCLS(etype));
11115 /* if (SPEC_OCLS(etype)->codesp ) */
11116 /* p_type = CPOINTER ; */
11118 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11119 /* p_type = FPOINTER ; */
11121 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11122 /* p_type = PPOINTER; */
11124 /* if (SPEC_OCLS(etype) == idata ) */
11125 /* p_type = IPOINTER ; */
11127 /* p_type = POINTER ; */
11130 /* the first two bytes are known */
11131 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
11132 size = GPTRSIZE - 1;
11135 if(offset < AOP_SIZE(right)) {
11136 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
11137 if ((AOP_TYPE(right) == AOP_PCODE) &&
11138 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11139 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11140 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11142 pic16_aopPut(AOP(result),
11143 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11147 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11150 /* the last byte depending on type */
11154 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11157 pic16_emitcode(";BUG!? ","%d",__LINE__);
11161 pic16_emitcode(";BUG!? ","%d",__LINE__);
11165 pic16_emitcode(";BUG!? ","%d",__LINE__);
11170 /* this should never happen */
11171 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11172 "got unknown pointer type");
11175 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
11179 /* just copy the pointers */
11180 size = AOP_SIZE(result);
11183 pic16_aopPut(AOP(result),
11184 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11193 /* so we now know that the size of destination is greater
11194 than the size of the source.
11195 Now, if the next iCode is an operator then we might be
11196 able to optimize the operation without performing a cast.
11198 if(genMixedOperation(ic))
11201 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11203 /* we move to result for the size of source */
11204 size = AOP_SIZE(right);
11207 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11208 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11212 /* now depending on the sign of the destination */
11213 size = AOP_SIZE(result) - AOP_SIZE(right);
11214 /* if unsigned or not an integral type */
11215 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11217 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11219 /* we need to extend the sign :( */
11222 /* Save one instruction of casting char to int */
11223 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11224 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11225 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
11227 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11230 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11232 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
11234 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
11237 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
11242 pic16_freeAsmop(right,NULL,ic,TRUE);
11243 pic16_freeAsmop(result,NULL,ic,TRUE);
11247 /*-----------------------------------------------------------------*/
11248 /* genDjnz - generate decrement & jump if not zero instrucion */
11249 /*-----------------------------------------------------------------*/
11250 static int genDjnz (iCode *ic, iCode *ifx)
11252 symbol *lbl, *lbl1;
11253 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11258 /* if the if condition has a false label
11259 then we cannot save */
11263 /* if the minus is not of the form
11265 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11266 !IS_OP_LITERAL(IC_RIGHT(ic)))
11269 if (operandLitValue(IC_RIGHT(ic)) != 1)
11272 /* if the size of this greater than one then no
11274 if (getSize(operandType(IC_RESULT(ic))) > 1)
11277 /* otherwise we can save BIG */
11278 lbl = newiTempLabel(NULL);
11279 lbl1= newiTempLabel(NULL);
11281 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11283 if (IS_AOP_PREG(IC_RESULT(ic))) {
11284 pic16_emitcode("dec","%s",
11285 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11286 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11287 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11291 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11292 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11294 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11295 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
11298 /* pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11299 /* pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11300 /* pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11301 /* pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11304 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11305 ifx->generated = 1;
11309 /*-----------------------------------------------------------------*/
11310 /* genReceive - generate code for a receive iCode */
11311 /*-----------------------------------------------------------------*/
11312 static void genReceive (iCode *ic)
11314 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11316 if (isOperandInFarSpace(IC_RESULT(ic)) &&
11317 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11318 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11320 int size = getSize(operandType(IC_RESULT(ic)));
11321 int offset = pic16_fReturnSizePic - size;
11324 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11325 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11329 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
11331 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11332 size = AOP_SIZE(IC_RESULT(ic));
11335 pic16_emitcode ("pop","acc");
11336 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11339 DEBUGpic16_emitcode ("; ***","2 %s %d",__FUNCTION__,__LINE__);
11342 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11344 assignResultValue(IC_RESULT(ic), 0);
11347 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11350 /*-----------------------------------------------------------------*/
11351 /* genDummyRead - generate code for dummy read of volatiles */
11352 /*-----------------------------------------------------------------*/
11354 genDummyRead (iCode * ic)
11356 pic16_emitcode ("; genDummyRead","");
11357 pic16_emitcode ("; not implemented","");
11362 /*-----------------------------------------------------------------*/
11363 /* genpic16Code - generate code for pic16 based controllers */
11364 /*-----------------------------------------------------------------*/
11366 * At this point, ralloc.c has gone through the iCode and attempted
11367 * to optimize in a way suitable for a PIC. Now we've got to generate
11368 * PIC instructions that correspond to the iCode.
11370 * Once the instructions are generated, we'll pass through both the
11371 * peep hole optimizer and the pCode optimizer.
11372 *-----------------------------------------------------------------*/
11374 void genpic16Code (iCode *lic)
11379 lineHead = lineCurr = NULL;
11381 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11382 pic16_addpBlock(pb);
11385 /* if debug information required */
11386 if (options.debug && currFunc) {
11388 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11393 for (ic = lic ; ic ; ic = ic->next ) {
11395 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11396 if ( cln != ic->lineno ) {
11397 if ( options.debug ) {
11398 debugFile->writeCLine (ic);
11401 if(!options.noCcodeInAsm) {
11402 pic16_addpCode2pBlock(pb,
11403 pic16_newpCodeCSource(ic->lineno, ic->filename,
11404 printCLine(ic->filename, ic->lineno)));
11410 if(options.iCodeInAsm) {
11412 /* insert here code to print iCode as comment */
11413 l = Safe_strdup(printILine(ic));
11414 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11417 /* if the result is marked as
11418 spilt and rematerializable or code for
11419 this has already been generated then
11421 if (resultRemat(ic) || ic->generated )
11424 /* depending on the operation */
11443 /* IPOP happens only when trying to restore a
11444 spilt live range, if there is an ifx statement
11445 following this pop then the if statement might
11446 be using some of the registers being popped which
11447 would destroy the contents of the register so
11448 we need to check for this condition and handle it */
11450 ic->next->op == IFX &&
11451 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
11452 genIfx (ic->next,ic);
11470 genEndFunction (ic);
11486 pic16_genPlus (ic) ;
11490 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11491 pic16_genMinus (ic);
11507 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
11511 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11518 /* note these two are xlated by algebraic equivalence
11519 during parsing SDCC.y */
11520 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11521 "got '>=' or '<=' shouldn't have come here");
11525 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11537 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11541 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11545 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11569 genRightShift (ic);
11572 case GET_VALUE_AT_ADDRESS:
11577 if (POINTER_SET(ic))
11604 addSet(&_G.sendSet,ic);
11607 case DUMMY_READ_VOLATILE:
11617 /* now we are ready to call the
11618 peep hole optimizer */
11619 if (!options.nopeep) {
11620 peepHole (&lineHead);
11622 /* now do the actual printing */
11623 printLine (lineHead,codeOutFile);
11626 DFPRINTF((stderr,"printing pBlock\n\n"));
11627 pic16_printpBlock(stdout,pb);