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;
3292 addSet(&absSymSet, abSym);
3297 /* create the function header */
3298 pic16_emitcode(";","-----------------------------------------");
3299 pic16_emitcode(";"," function %s",sym->name);
3300 pic16_emitcode(";","-----------------------------------------");
3302 pic16_emitcode("","%s:",sym->rname);
3303 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3309 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3310 if(!strcmp(ab->name, sym->name)) {
3311 pic16_pBlockConvert2Absolute(pb);
3318 if(IFFUNC_ISNAKED(ftype)) {
3319 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3323 /* if critical function then turn interrupts off */
3324 if (IFFUNC_ISCRITICAL(ftype))
3325 pic16_emitcode("clr","ea");
3327 /* if this is an interrupt service routine then
3328 * save acc, b, dpl, dph */
3329 if (IFFUNC_ISISR(sym->type)) {
3331 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3332 if(!(_G.interruptvector == 1)) {
3334 /* do not save WREG,STATUS,BSR for high priority interrupts
3335 * because they are stored in the hardware shadow registers already */
3337 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3338 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3339 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3342 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3343 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3344 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3345 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3347 // pic16_pBlockConvert2ISR(pb);
3349 /* if any registers used */
3350 if (sym->regsUsed) {
3351 /* save the registers used */
3352 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3353 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3354 if (bitVectBitValue(sym->regsUsed,i)) {
3355 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3356 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3357 // pic16_regWithIdx(i)->name);
3359 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3365 /* emit code to setup stack frame if user enabled,
3366 * and function is not main() */
3368 // fprintf(stderr, "function name: %s\n", sym->name);
3369 if(strcmp(sym->name, "main")) {
3370 if(/*!options.ommitFramePtr || */sym->regsUsed) {
3371 /* setup the stack frame */
3372 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3373 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3374 if(STACK_MODEL_LARGE)
3375 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3379 /* if callee-save to be used for this function
3380 * then save the registers being used in this function */
3381 // if (IFFUNC_CALLEESAVES(sym->type))
3385 // fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3387 // pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3389 /* if any registers used */
3390 if (sym->regsUsed) {
3391 /* save the registers used */
3392 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3393 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3394 if (bitVectBitValue(sym->regsUsed,i)) {
3396 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3397 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3398 // pic16_regWithIdx(i)->name);
3400 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3402 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3403 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3404 // &pic16_pc_postdec1, 0));
3416 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3418 if (options.useXstack) {
3419 pic16_emitcode("mov","r0,%s",spname);
3420 pic16_emitcode("mov","a,_bp");
3421 pic16_emitcode("movx","@r0,a");
3422 pic16_emitcode("inc","%s",spname);
3424 /* set up the stack */
3425 pic16_emitcode ("push","_bp"); /* save the callers stack */
3427 pic16_emitcode ("mov","_bp,%s",spname);
3430 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3432 /* adjust the stack for the function */
3437 werror(W_STACK_OVERFLOW,sym->name);
3439 if (i > 3 && sym->recvSize < 4) {
3440 pic16_emitcode ("mov","a,sp");
3441 pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3442 pic16_emitcode ("mov","sp,a");
3445 pic16_emitcode("inc","sp");
3449 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3451 pic16_emitcode ("mov","a,_spx");
3452 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3453 pic16_emitcode ("mov","_spx,a");
3458 /*-----------------------------------------------------------------*/
3459 /* genEndFunction - generates epilogue for functions */
3460 /*-----------------------------------------------------------------*/
3461 static void genEndFunction (iCode *ic)
3463 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3465 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3467 if(IFFUNC_ISNAKED(sym->type)) {
3468 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3473 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3475 pic16_emitcode ("mov","%s,_bp",spname);
3479 /* if use external stack but some variables were
3480 added to the local stack then decrement the
3482 if (options.useXstack && sym->stack) {
3483 pic16_emitcode("mov","a,sp");
3484 pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3485 pic16_emitcode("mov","sp,a");
3490 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3491 if (options.useXstack) {
3492 pic16_emitcode("mov","r0,%s",spname);
3493 pic16_emitcode("movx","a,@r0");
3494 pic16_emitcode("mov","_bp,a");
3495 pic16_emitcode("dec","%s",spname);
3499 pic16_emitcode ("pop","_bp");
3504 if (IFFUNC_ISISR(sym->type)) {
3505 /* now we need to restore the registers */
3506 /* if any registers used */
3507 if (sym->regsUsed) {
3510 /* restore registers used */
3511 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3512 for ( i = sym->regsUsed->size; i >= 0; i--) {
3513 if (bitVectBitValue(sym->regsUsed,i)) {
3515 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3516 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3517 // pic16_regWithIdx(i)->name);
3519 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3521 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3522 // &pic16_pc_preinc1,
3523 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3529 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3530 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3531 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3532 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3534 if(!(_G.interruptvector == 1)) {
3535 /* do not restore interrupt vector for WREG,STATUS,BSR
3536 * for high priority interrupt, see genFunction */
3538 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3539 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3540 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3543 _G.interruptvector = 0; /* sanity check */
3545 // pic16_pBlockConvert2ISR(pb);
3548 /* if debug then send end of function */
3549 /* if (options.debug && currFunc) */
3551 debugFile->writeEndFunction (currFunc, ic, 1);
3554 pic16_emitpcodeNULLop(POC_RETFIE);
3556 if (IFFUNC_ISCRITICAL(sym->type))
3557 pic16_emitcode("setb","ea");
3560 // pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3562 /* if any registers used */
3563 if (sym->regsUsed) {
3565 /* save the registers used */
3566 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3567 for ( i = sym->regsUsed->size; i >= 0; i--) {
3568 if (bitVectBitValue(sym->regsUsed,i)) {
3570 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3571 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3572 // pic16_regWithIdx(i)->name);
3574 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3576 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3577 // &pic16_pc_preinc1,
3578 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3585 pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3586 /* if debug then send end of function */
3588 debugFile->writeEndFunction (currFunc, ic, 1);
3591 /* insert code to restore stack frame, if user enabled it
3592 * and function is not main() */
3595 if(strcmp(sym->name, "main")) {
3596 if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3597 /* restore stack frame */
3598 if(STACK_MODEL_LARGE)
3599 pic16_emitpcode(POC_MOVFF,
3600 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3601 pic16_emitpcode(POC_MOVFF,
3602 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3606 pic16_emitcode ("return","");
3607 pic16_emitpcodeNULLop(POC_RETURN);
3609 /* Mark the end of a function */
3610 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3616 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3620 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3622 if(dest->type != PO_WREG)
3623 pic16_emitpcode(POC_MOVWF, dest);
3625 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3626 pic16_popGet(AOP(op), offset), dest));
3630 /*-----------------------------------------------------------------*/
3631 /* genRet - generate code for return statement */
3632 /*-----------------------------------------------------------------*/
3633 static void genRet (iCode *ic)
3638 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3639 /* if we have no return value then
3640 * just generate the "ret" */
3645 /* we have something to return then
3646 * move the return value into place */
3647 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3648 size = AOP_SIZE(IC_LEFT(ic));
3652 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3653 // pic16_emitpcode(POC_MOVFF,
3654 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3657 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3658 // pic16_emitpcode(POC_MOVFF,
3659 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3662 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3663 // pic16_emitpcode(POC_MOVFF,
3664 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3667 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3669 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3670 // pic16_emitpcode(POC_MOVFF,
3671 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3674 /* >32-bits, setup stack and FSR0 */
3676 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3677 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3679 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3681 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3686 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3687 pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3689 if(STACK_MODEL_LARGE) {
3690 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3691 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3693 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3698 /* old code, left here for reference -- VR */
3702 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3704 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3705 pic16_emitpcomment("push %s",l);
3708 DEBUGpic16_emitcode(";", "%d", __LINE__);
3709 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3710 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3712 if (strcmp(fReturn[offset],l)) {
3713 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3714 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3715 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3717 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3721 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3731 if (strcmp(fReturn[pushed],"a"))
3732 pic16_emitcode("pop",fReturn[pushed]);
3734 pic16_emitcode("pop","acc");
3740 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3743 /* generate a jump to the return label
3744 * if the next is not the return statement */
3745 if (!(ic->next && ic->next->op == LABEL
3746 && IC_LABEL(ic->next) == returnLabel)) {
3748 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3749 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3753 /*-----------------------------------------------------------------*/
3754 /* genLabel - generates a label */
3755 /*-----------------------------------------------------------------*/
3756 static void genLabel (iCode *ic)
3760 /* special case never generate */
3761 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3762 if (IC_LABEL(ic) == entryLabel)
3765 pic16_emitpLabel(IC_LABEL(ic)->key);
3766 pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3769 /*-----------------------------------------------------------------*/
3770 /* genGoto - generates a goto */
3771 /*-----------------------------------------------------------------*/
3773 static void genGoto (iCode *ic)
3775 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3776 pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3780 /*-----------------------------------------------------------------*/
3781 /* genMultbits :- multiplication of bits */
3782 /*-----------------------------------------------------------------*/
3783 static void genMultbits (operand *left,
3787 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3789 if(!pic16_sameRegs(AOP(result),AOP(right)))
3790 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3792 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3793 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3794 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3799 /*-----------------------------------------------------------------*/
3800 /* genMultOneByte : 8 bit multiplication & division */
3801 /*-----------------------------------------------------------------*/
3802 static void genMultOneByte (operand *left,
3807 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3808 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3809 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3811 /* (if two literals, the value is computed before) */
3812 /* if one literal, literal on the right */
3813 if (AOP_TYPE(left) == AOP_LIT){
3819 /* size is already checked in genMult == 1 */
3820 // size = AOP_SIZE(result);
3822 if (AOP_TYPE(right) == AOP_LIT){
3823 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3824 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3825 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3826 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3828 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3829 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3830 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3831 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3834 pic16_genMult8X8_8 (left, right,result);
3837 /*-----------------------------------------------------------------*/
3838 /* genMultOneWord : 16 bit multiplication */
3839 /*-----------------------------------------------------------------*/
3840 static void genMultOneWord (operand *left,
3845 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3846 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3847 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3849 /* (if two literals, the value is computed before)
3850 * if one literal, literal on the right */
3851 if (AOP_TYPE(left) == AOP_LIT){
3857 /* size is checked already == 2 */
3858 // size = AOP_SIZE(result);
3860 if (AOP_TYPE(right) == AOP_LIT) {
3861 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3862 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3863 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3864 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3866 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3867 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3868 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3869 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3872 pic16_genMult16X16_16(left, right,result);
3875 /*-----------------------------------------------------------------*/
3876 /* genMultOneLong : 32 bit multiplication */
3877 /*-----------------------------------------------------------------*/
3878 static void genMultOneLong (operand *left,
3883 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3884 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3885 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3887 /* (if two literals, the value is computed before)
3888 * if one literal, literal on the right */
3889 if (AOP_TYPE(left) == AOP_LIT){
3895 /* size is checked already == 4 */
3896 // size = AOP_SIZE(result);
3898 if (AOP_TYPE(right) == AOP_LIT) {
3899 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3900 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3901 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3902 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3904 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3905 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3906 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3907 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3910 pic16_genMult32X32_32(left, right,result);
3915 /*-----------------------------------------------------------------*/
3916 /* genMult - generates code for multiplication */
3917 /*-----------------------------------------------------------------*/
3918 static void genMult (iCode *ic)
3920 operand *left = IC_LEFT(ic);
3921 operand *right = IC_RIGHT(ic);
3922 operand *result= IC_RESULT(ic);
3924 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3925 /* assign the amsops */
3926 pic16_aopOp (left,ic,FALSE);
3927 pic16_aopOp (right,ic,FALSE);
3928 pic16_aopOp (result,ic,TRUE);
3930 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3932 /* special cases first *
3934 if (AOP_TYPE(left) == AOP_CRY
3935 && AOP_TYPE(right)== AOP_CRY) {
3936 genMultbits(left,right,result);
3940 /* if both are of size == 1 */
3941 if(AOP_SIZE(left) == 1
3942 && AOP_SIZE(right) == 1) {
3943 genMultOneByte(left,right,result);
3947 /* if both are of size == 2 */
3948 if(AOP_SIZE(left) == 2
3949 && AOP_SIZE(right) == 2) {
3950 genMultOneWord(left, right, result);
3954 /* if both are of size == 4 */
3955 if(AOP_SIZE(left) == 4
3956 && AOP_SIZE(right) == 4) {
3957 genMultOneLong(left, right, result);
3961 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3964 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3965 /* should have been converted to function call */
3969 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3970 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3971 pic16_freeAsmop(result,NULL,ic,TRUE);
3974 /*-----------------------------------------------------------------*/
3975 /* genDivbits :- division of bits */
3976 /*-----------------------------------------------------------------*/
3977 static void genDivbits (operand *left,
3984 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3985 /* the result must be bit */
3986 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3987 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3991 pic16_emitcode("div","ab");
3992 pic16_emitcode("rrc","a");
3993 pic16_aopPut(AOP(result),"c",0);
3996 /*-----------------------------------------------------------------*/
3997 /* genDivOneByte : 8 bit division */
3998 /*-----------------------------------------------------------------*/
3999 static void genDivOneByte (operand *left,
4003 sym_link *opetype = operandType(result);
4008 /* result = divident / divisor
4009 * - divident may be a register or a literal,
4010 * - divisor may be a register or a literal,
4011 * so there are 3 cases (literal / literal is optimized
4012 * by the front-end) to handle.
4013 * In addition we must handle signed and unsigned, which
4014 * result in 6 final different cases -- VR */
4016 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4017 size = AOP_SIZE(result) - 1;
4019 /* signed or unsigned */
4020 if (SPEC_USIGN(opetype)) {
4021 pCodeOp *pct1, /* count */
4024 symbol *label1, *label2, *label3;;
4027 /* unsigned is easy */
4029 pct1 = pic16_popGetTempReg();
4030 pct2 = pic16_popGetTempReg();
4031 pct3 = pic16_popGetTempReg();
4033 label1 = newiTempLabel(NULL);
4034 label2 = newiTempLabel(NULL);
4035 label3 = newiTempLabel(NULL);
4037 /* the following algorithm is extracted from divuint.c */
4039 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4040 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4042 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4044 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4046 pic16_emitpLabel(label1->key);
4049 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4053 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4057 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4059 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4060 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4062 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4063 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4064 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4066 pic16_emitpLabel( label3->key );
4067 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4068 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4072 pic16_emitpLabel(label2->key);
4073 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4074 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4075 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4077 /* result is in wreg */
4078 if(AOP_TYPE(result) != AOP_ACC)
4079 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4081 pic16_popReleaseTempReg( pct3 );
4082 pic16_popReleaseTempReg( pct2 );
4083 pic16_popReleaseTempReg( pct1 );
4088 /* signed is a little bit more difficult */
4090 /* save the signs of the operands */
4091 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4093 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4094 pic16_emitcode("push","acc"); /* save it on the stack */
4096 /* now sign adjust for both left & right */
4097 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4099 lbl = newiTempLabel(NULL);
4100 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4101 pic16_emitcode("cpl","a");
4102 pic16_emitcode("inc","a");
4103 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4104 pic16_emitcode("mov","b,a");
4106 /* sign adjust left side */
4107 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4110 lbl = newiTempLabel(NULL);
4111 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4112 pic16_emitcode("cpl","a");
4113 pic16_emitcode("inc","a");
4114 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4116 /* now the division */
4117 pic16_emitcode("div","ab");
4118 /* we are interested in the lower order
4120 pic16_emitcode("mov","b,a");
4121 lbl = newiTempLabel(NULL);
4122 pic16_emitcode("pop","acc");
4123 /* if there was an over flow we don't
4124 adjust the sign of the result */
4125 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4126 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4128 pic16_emitcode("clr","a");
4129 pic16_emitcode("subb","a,b");
4130 pic16_emitcode("mov","b,a");
4131 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4133 /* now we are done */
4134 pic16_aopPut(AOP(result),"b",0);
4136 pic16_emitcode("mov","c,b.7");
4137 pic16_emitcode("subb","a,acc");
4140 pic16_aopPut(AOP(result),"a",offset++);
4144 /*-----------------------------------------------------------------*/
4145 /* genDiv - generates code for division */
4146 /*-----------------------------------------------------------------*/
4147 static void genDiv (iCode *ic)
4149 operand *left = IC_LEFT(ic);
4150 operand *right = IC_RIGHT(ic);
4151 operand *result= IC_RESULT(ic);
4154 /* Division is a very lengthy algorithm, so it is better
4155 * to call support routines than inlining algorithm.
4156 * Division functions written here just in case someone
4157 * wants to inline and not use the support libraries -- VR */
4159 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4160 /* assign the amsops */
4161 pic16_aopOp (left,ic,FALSE);
4162 pic16_aopOp (right,ic,FALSE);
4163 pic16_aopOp (result,ic,TRUE);
4165 /* special cases first */
4167 if (AOP_TYPE(left) == AOP_CRY &&
4168 AOP_TYPE(right)== AOP_CRY) {
4169 genDivbits(left,right,result);
4173 /* if both are of size == 1 */
4174 if (AOP_SIZE(left) == 1 &&
4175 AOP_SIZE(right) == 1 ) {
4176 genDivOneByte(left,right,result);
4180 /* should have been converted to function call */
4183 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4184 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4185 pic16_freeAsmop(result,NULL,ic,TRUE);
4188 /*-----------------------------------------------------------------*/
4189 /* genModbits :- modulus of bits */
4190 /*-----------------------------------------------------------------*/
4191 static void genModbits (operand *left,
4198 /* the result must be bit */
4199 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4200 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4204 pic16_emitcode("div","ab");
4205 pic16_emitcode("mov","a,b");
4206 pic16_emitcode("rrc","a");
4207 pic16_aopPut(AOP(result),"c",0);
4210 /*-----------------------------------------------------------------*/
4211 /* genModOneByte : 8 bit modulus */
4212 /*-----------------------------------------------------------------*/
4213 static void genModOneByte (operand *left,
4217 sym_link *opetype = operandType(result);
4221 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4222 /* signed or unsigned */
4223 if (SPEC_USIGN(opetype)) {
4224 /* unsigned is easy */
4225 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4226 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4228 pic16_emitcode("div","ab");
4229 pic16_aopPut(AOP(result),"b",0);
4233 /* signed is a little bit more difficult */
4235 /* save the signs of the operands */
4236 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4239 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4240 pic16_emitcode("push","acc"); /* save it on the stack */
4242 /* now sign adjust for both left & right */
4243 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4246 lbl = newiTempLabel(NULL);
4247 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4248 pic16_emitcode("cpl","a");
4249 pic16_emitcode("inc","a");
4250 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4251 pic16_emitcode("mov","b,a");
4253 /* sign adjust left side */
4254 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4257 lbl = newiTempLabel(NULL);
4258 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4259 pic16_emitcode("cpl","a");
4260 pic16_emitcode("inc","a");
4261 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4263 /* now the multiplication */
4264 pic16_emitcode("div","ab");
4265 /* we are interested in the lower order
4267 lbl = newiTempLabel(NULL);
4268 pic16_emitcode("pop","acc");
4269 /* if there was an over flow we don't
4270 adjust the sign of the result */
4271 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4272 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4274 pic16_emitcode("clr","a");
4275 pic16_emitcode("subb","a,b");
4276 pic16_emitcode("mov","b,a");
4277 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4279 /* now we are done */
4280 pic16_aopPut(AOP(result),"b",0);
4284 /*-----------------------------------------------------------------*/
4285 /* genMod - generates code for division */
4286 /*-----------------------------------------------------------------*/
4287 static void genMod (iCode *ic)
4289 operand *left = IC_LEFT(ic);
4290 operand *right = IC_RIGHT(ic);
4291 operand *result= IC_RESULT(ic);
4293 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4294 /* assign the amsops */
4295 pic16_aopOp (left,ic,FALSE);
4296 pic16_aopOp (right,ic,FALSE);
4297 pic16_aopOp (result,ic,TRUE);
4299 /* special cases first */
4301 if (AOP_TYPE(left) == AOP_CRY &&
4302 AOP_TYPE(right)== AOP_CRY) {
4303 genModbits(left,right,result);
4307 /* if both are of size == 1 */
4308 if (AOP_SIZE(left) == 1 &&
4309 AOP_SIZE(right) == 1 ) {
4310 genModOneByte(left,right,result);
4314 /* should have been converted to function call */
4318 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4319 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4320 pic16_freeAsmop(result,NULL,ic,TRUE);
4323 /*-----------------------------------------------------------------*/
4324 /* genIfxJump :- will create a jump depending on the ifx */
4325 /*-----------------------------------------------------------------*/
4327 note: May need to add parameter to indicate when a variable is in bit space.
4329 static void genIfxJump (iCode *ic, char *jval)
4332 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4333 /* if true label then we jump if condition
4335 if ( IC_TRUE(ic) ) {
4337 if(strcmp(jval,"a") == 0)
4339 else if (strcmp(jval,"c") == 0)
4342 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4343 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1));
4346 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4347 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4351 /* false label is present */
4352 if(strcmp(jval,"a") == 0)
4354 else if (strcmp(jval,"c") == 0)
4357 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4358 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1));
4361 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4362 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4367 /* mark the icode as generated */
4374 /*-----------------------------------------------------------------*/
4376 /*-----------------------------------------------------------------*/
4377 static void genSkip(iCode *ifx,int status_bit)
4379 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4383 if ( IC_TRUE(ifx) ) {
4384 switch(status_bit) {
4399 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4400 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4404 switch(status_bit) {
4418 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4419 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4426 /*-----------------------------------------------------------------*/
4428 /*-----------------------------------------------------------------*/
4429 static void genSkipc(resolvedIfx *rifx)
4431 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4441 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4442 rifx->generated = 1;
4445 /*-----------------------------------------------------------------*/
4447 /*-----------------------------------------------------------------*/
4448 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4450 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4455 if( (rifx->condition ^ invert_condition) & 1)
4460 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4461 rifx->generated = 1;
4465 /*-----------------------------------------------------------------*/
4467 /*-----------------------------------------------------------------*/
4468 static void genSkipz(iCode *ifx, int condition)
4479 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4481 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4484 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4486 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4491 /*-----------------------------------------------------------------*/
4493 /*-----------------------------------------------------------------*/
4494 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4500 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4502 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4505 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4506 rifx->generated = 1;
4510 /*-----------------------------------------------------------------*/
4511 /* genChkZeroes :- greater or less than comparison */
4512 /* For each byte in a literal that is zero, inclusive or the */
4513 /* the corresponding byte in the operand with W */
4514 /* returns true if any of the bytes are zero */
4515 /*-----------------------------------------------------------------*/
4516 static int genChkZeroes(operand *op, int lit, int size)
4523 i = (lit >> (size*8)) & 0xff;
4527 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4529 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4538 /*-----------------------------------------------------------------*/
4539 /* genCmp :- greater or less than comparison */
4540 /*-----------------------------------------------------------------*/
4541 static void genCmp (operand *left,operand *right,
4542 operand *result, iCode *ifx, int sign)
4544 int size; //, offset = 0 ;
4545 unsigned long lit = 0L,i = 0;
4546 resolvedIfx rFalseIfx;
4547 // resolvedIfx rTrueIfx;
4549 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4552 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4553 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4557 resolveIfx(&rFalseIfx,ifx);
4558 truelbl = newiTempLabel(NULL);
4559 size = max(AOP_SIZE(left),AOP_SIZE(right));
4561 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4565 /* if literal is on the right then swap with left */
4566 if ((AOP_TYPE(right) == AOP_LIT)) {
4567 operand *tmp = right ;
4568 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4569 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4572 lit = (lit - 1) & mask;
4575 rFalseIfx.condition ^= 1;
4578 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4579 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4583 //if(IC_TRUE(ifx) == NULL)
4584 /* if left & right are bit variables */
4585 if (AOP_TYPE(left) == AOP_CRY &&
4586 AOP_TYPE(right) == AOP_CRY ) {
4587 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4588 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4590 /* subtract right from left if at the
4591 end the carry flag is set then we know that
4592 left is greater than right */
4594 symbol *lbl = newiTempLabel(NULL);
4597 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4598 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+labelOffset, lbl->key+100+labelOffset);
4602 if(AOP_TYPE(right) == AOP_LIT) {
4604 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4606 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4613 genSkipCond(&rFalseIfx,left,size-1,7);
4615 /* no need to compare to 0...*/
4616 /* NOTE: this is a de-generate compare that most certainly
4617 * creates some dead code. */
4618 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4620 if(ifx) ifx->generated = 1;
4627 //i = (lit >> (size*8)) & 0xff;
4628 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4630 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4632 i = ((0-lit) & 0xff);
4635 /* lit is 0x7f, all signed chars are less than
4636 * this except for 0x7f itself */
4637 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4638 genSkipz2(&rFalseIfx,0);
4640 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4641 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4642 genSkipc(&rFalseIfx);
4647 genSkipz2(&rFalseIfx,1);
4649 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4650 genSkipc(&rFalseIfx);
4654 if(ifx) ifx->generated = 1;
4658 /* chars are out of the way. now do ints and longs */
4661 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4668 genSkipCond(&rFalseIfx,left,size,7);
4669 if(ifx) ifx->generated = 1;
4674 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4676 //rFalseIfx.condition ^= 1;
4677 //genSkipCond(&rFalseIfx,left,size,7);
4678 //rFalseIfx.condition ^= 1;
4680 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4681 if(rFalseIfx.condition)
4682 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4684 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4686 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4687 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4688 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4691 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4693 if(rFalseIfx.condition) {
4695 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4701 genSkipc(&rFalseIfx);
4702 pic16_emitpLabel(truelbl->key);
4703 if(ifx) ifx->generated = 1;
4710 if( (lit & 0xff) == 0) {
4711 /* lower byte is zero */
4712 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4713 i = ((lit >> 8) & 0xff) ^0x80;
4714 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4715 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4716 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4717 genSkipc(&rFalseIfx);
4720 if(ifx) ifx->generated = 1;
4725 /* Special cases for signed longs */
4726 if( (lit & 0xffffff) == 0) {
4727 /* lower byte is zero */
4728 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4729 i = ((lit >> 8*3) & 0xff) ^0x80;
4730 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4731 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4732 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4733 genSkipc(&rFalseIfx);
4736 if(ifx) ifx->generated = 1;
4744 if(lit & (0x80 << (size*8))) {
4745 /* lit is negative */
4746 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4748 //genSkipCond(&rFalseIfx,left,size,7);
4750 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4752 if(rFalseIfx.condition)
4753 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4755 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4759 /* lit is positive */
4760 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4761 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4762 if(rFalseIfx.condition)
4763 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4765 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4770 This works, but is only good for ints.
4771 It also requires a "known zero" register.
4772 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4773 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4774 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
4775 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4776 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4777 genSkipc(&rFalseIfx);
4779 pic16_emitpLabel(truelbl->key);
4780 if(ifx) ifx->generated = 1;
4784 /* There are no more special cases, so perform a general compare */
4786 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4787 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4791 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4793 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4795 //rFalseIfx.condition ^= 1;
4796 genSkipc(&rFalseIfx);
4798 pic16_emitpLabel(truelbl->key);
4800 if(ifx) ifx->generated = 1;
4807 /* sign is out of the way. So now do an unsigned compare */
4808 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4811 /* General case - compare to an unsigned literal on the right.*/
4813 i = (lit >> (size*8)) & 0xff;
4814 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4815 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4817 i = (lit >> (size*8)) & 0xff;
4820 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4822 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4824 /* this byte of the lit is zero,
4825 *if it's not the last then OR in the variable */
4827 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4832 pic16_emitpLabel(lbl->key);
4833 // pic16_emitpLabel(truelbl->key);
4834 //if(emitFinalCheck)
4835 genSkipc(&rFalseIfx);
4837 pic16_emitpLabel(truelbl->key);
4839 if(ifx) ifx->generated = 1;
4846 if(AOP_TYPE(left) == AOP_LIT) {
4847 //symbol *lbl = newiTempLabel(NULL);
4849 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4852 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4855 if((lit == 0) && (sign == 0)){
4858 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4860 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4862 genSkipz2(&rFalseIfx,0);
4863 if(ifx) ifx->generated = 1;
4870 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4871 /* degenerate compare can never be true */
4872 if(rFalseIfx.condition == 0)
4873 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4875 if(ifx) ifx->generated = 1;
4880 /* signed comparisons to a literal byte */
4882 int lp1 = (lit+1) & 0xff;
4884 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4887 rFalseIfx.condition ^= 1;
4888 genSkipCond(&rFalseIfx,right,0,7);
4891 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4892 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4893 genSkipz2(&rFalseIfx,1);
4896 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4897 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4898 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4899 rFalseIfx.condition ^= 1;
4900 genSkipc(&rFalseIfx);
4904 /* unsigned comparisons to a literal byte */
4906 switch(lit & 0xff ) {
4908 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4909 genSkipz2(&rFalseIfx,0);
4912 rFalseIfx.condition ^= 1;
4913 genSkipCond(&rFalseIfx,right,0,7);
4917 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4918 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4919 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4920 rFalseIfx.condition ^= 1;
4921 if (AOP_TYPE(result) == AOP_CRY)
4922 genSkipc(&rFalseIfx);
4924 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4925 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4931 if(ifx) ifx->generated = 1;
4932 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
4938 /* Size is greater than 1 */
4946 /* this means lit = 0xffffffff, or -1 */
4949 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4950 rFalseIfx.condition ^= 1;
4951 genSkipCond(&rFalseIfx,right,size,7);
4952 if(ifx) ifx->generated = 1;
4959 if(rFalseIfx.condition) {
4960 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4961 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4964 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4966 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4970 if(rFalseIfx.condition) {
4971 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4972 pic16_emitpLabel(truelbl->key);
4974 rFalseIfx.condition ^= 1;
4975 genSkipCond(&rFalseIfx,right,s,7);
4978 if(ifx) ifx->generated = 1;
4982 if((size == 1) && (0 == (lp1&0xff))) {
4983 /* lower byte of signed word is zero */
4984 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4985 i = ((lp1 >> 8) & 0xff) ^0x80;
4986 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4987 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4988 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4989 rFalseIfx.condition ^= 1;
4990 genSkipc(&rFalseIfx);
4993 if(ifx) ifx->generated = 1;
4997 if(lit & (0x80 << (size*8))) {
4998 /* Lit is less than zero */
4999 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5000 //rFalseIfx.condition ^= 1;
5001 //genSkipCond(&rFalseIfx,left,size,7);
5002 //rFalseIfx.condition ^= 1;
5003 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5004 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5006 if(rFalseIfx.condition)
5007 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5009 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5013 /* Lit is greater than or equal to zero */
5014 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5015 //rFalseIfx.condition ^= 1;
5016 //genSkipCond(&rFalseIfx,right,size,7);
5017 //rFalseIfx.condition ^= 1;
5019 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5020 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5022 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5023 if(rFalseIfx.condition)
5024 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5026 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5031 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5032 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5036 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5038 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5040 rFalseIfx.condition ^= 1;
5041 //rFalseIfx.condition = 1;
5042 genSkipc(&rFalseIfx);
5044 pic16_emitpLabel(truelbl->key);
5046 if(ifx) ifx->generated = 1;
5051 /* compare word or long to an unsigned literal on the right.*/
5056 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5059 break; /* handled above */
5062 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5064 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5065 genSkipz2(&rFalseIfx,0);
5069 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5071 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5074 if(rFalseIfx.condition)
5075 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5077 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5080 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5081 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5083 rFalseIfx.condition ^= 1;
5084 genSkipc(&rFalseIfx);
5087 pic16_emitpLabel(truelbl->key);
5089 if(ifx) ifx->generated = 1;
5095 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5096 i = (lit >> (size*8)) & 0xff;
5098 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5099 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5102 i = (lit >> (size*8)) & 0xff;
5105 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5107 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5109 /* this byte of the lit is zero,
5110 * if it's not the last then OR in the variable */
5112 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5117 pic16_emitpLabel(lbl->key);
5119 rFalseIfx.condition ^= 1;
5121 genSkipc(&rFalseIfx);
5125 pic16_emitpLabel(truelbl->key);
5126 if(ifx) ifx->generated = 1;
5130 /* Compare two variables */
5132 DEBUGpic16_emitcode(";sign","%d",sign);
5136 /* Sigh. thus sucks... */
5138 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5139 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5140 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5141 pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5142 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5143 pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5145 /* Signed char comparison */
5146 /* Special thanks to Nikolai Golovchenko for this snippet */
5147 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5148 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5149 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5150 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5151 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5152 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5154 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5155 genSkipc(&rFalseIfx);
5157 if(ifx) ifx->generated = 1;
5163 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5164 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5168 /* The rest of the bytes of a multi-byte compare */
5172 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5175 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5176 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5181 pic16_emitpLabel(lbl->key);
5183 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5184 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5185 (AOP_TYPE(result) == AOP_REG)) {
5186 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5187 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5189 genSkipc(&rFalseIfx);
5191 //genSkipc(&rFalseIfx);
5192 if(ifx) ifx->generated = 1;
5199 if ((AOP_TYPE(result) != AOP_CRY)
5200 && AOP_SIZE(result)) {
5201 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5202 // pic16_emitpLabel( rFalseIfx.lbl->key );
5204 pic16_outBitC(result);
5206 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5207 /* if the result is used in the next
5208 ifx conditional branch then generate
5209 code a little differently */
5211 genIfxJump (ifx,"c");
5213 pic16_outBitC(result);
5214 /* leave the result in acc */
5219 /*-----------------------------------------------------------------*/
5220 /* genCmpGt :- greater than comparison */
5221 /*-----------------------------------------------------------------*/
5222 static void genCmpGt (iCode *ic, iCode *ifx)
5224 operand *left, *right, *result;
5225 sym_link *letype , *retype;
5228 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5230 right= IC_RIGHT(ic);
5231 result = IC_RESULT(ic);
5233 letype = getSpec(operandType(left));
5234 retype =getSpec(operandType(right));
5235 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5236 /* assign the amsops */
5237 pic16_aopOp (left,ic,FALSE);
5238 pic16_aopOp (right,ic,FALSE);
5239 pic16_aopOp (result,ic,TRUE);
5241 genCmp(right, left, result, ifx, sign);
5243 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5244 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5245 pic16_freeAsmop(result,NULL,ic,TRUE);
5248 /*-----------------------------------------------------------------*/
5249 /* genCmpLt - less than comparisons */
5250 /*-----------------------------------------------------------------*/
5251 static void genCmpLt (iCode *ic, iCode *ifx)
5253 operand *left, *right, *result;
5254 sym_link *letype , *retype;
5257 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5259 right= IC_RIGHT(ic);
5260 result = IC_RESULT(ic);
5262 letype = getSpec(operandType(left));
5263 retype =getSpec(operandType(right));
5264 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5266 /* assign the amsops */
5267 pic16_aopOp (left,ic,FALSE);
5268 pic16_aopOp (right,ic,FALSE);
5269 pic16_aopOp (result,ic,TRUE);
5271 genCmp(left, right, result, ifx, sign);
5273 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5274 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5275 pic16_freeAsmop(result,NULL,ic,TRUE);
5280 // FIXME reenable literal optimisation when the pic16 port is stable
5282 /*-----------------------------------------------------------------*/
5283 /* genc16bit2lit - compare a 16 bit value to a literal */
5284 /*-----------------------------------------------------------------*/
5285 static void genc16bit2lit(operand *op, int lit, int offset)
5289 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
5290 if( (lit&0xff) == 0)
5295 switch( BYTEofLONG(lit,i)) {
5297 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5300 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5303 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5306 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5307 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5312 switch( BYTEofLONG(lit,i)) {
5314 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5318 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5322 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5325 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5327 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5336 /*-----------------------------------------------------------------*/
5337 /* gencjneshort - compare and jump if not equal */
5338 /*-----------------------------------------------------------------*/
5339 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5341 int size = max(AOP_SIZE(left),AOP_SIZE(right));
5343 int res_offset = 0; /* the result may be a different size then left or right */
5344 int res_size = AOP_SIZE(result);
5346 symbol *lbl, *lbl_done;
5348 unsigned long lit = 0L;
5349 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5351 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5352 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5354 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
5355 resolveIfx(&rIfx,ifx);
5356 lbl = newiTempLabel(NULL);
5357 lbl_done = newiTempLabel(NULL);
5360 /* if the left side is a literal or
5361 if the right is in a pointer register and left
5363 if ((AOP_TYPE(left) == AOP_LIT) ||
5364 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5369 if(AOP_TYPE(right) == AOP_LIT)
5370 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5372 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5373 preserve_result = 1;
5375 if(result && !preserve_result)
5378 for(i = 0; i < AOP_SIZE(result); i++)
5379 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5383 /* if the right side is a literal then anything goes */
5384 if (AOP_TYPE(right) == AOP_LIT &&
5385 AOP_TYPE(left) != AOP_DIR ) {
5388 genc16bit2lit(left, lit, 0);
5390 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5393 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5396 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5397 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5399 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5403 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5405 if(res_offset < res_size-1)
5413 /* if the right side is in a register or in direct space or
5414 if the left is a pointer register & right is not */
5415 else if (AOP_TYPE(right) == AOP_REG ||
5416 AOP_TYPE(right) == AOP_DIR ||
5417 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5418 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5419 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5420 int lbl_key = lbl->key;
5423 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5424 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5426 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5427 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5428 __FUNCTION__,__LINE__);
5432 /* switch(size) { */
5434 /* genc16bit2lit(left, lit, 0); */
5436 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5441 if((AOP_TYPE(left) == AOP_DIR) &&
5442 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5444 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5445 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5447 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5449 switch (lit & 0xff) {
5451 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5454 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5455 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5456 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5460 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5461 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5462 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5463 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5467 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5468 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5473 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5476 if(AOP_TYPE(result) == AOP_CRY) {
5477 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5482 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5484 /* fix me. probably need to check result size too */
5485 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5490 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5491 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5498 if(res_offset < res_size-1)
5503 } else if(AOP_TYPE(right) == AOP_REG &&
5504 AOP_TYPE(left) != AOP_DIR){
5507 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5508 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5509 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5514 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5516 if(res_offset < res_size-1)
5521 /* right is a pointer reg need both a & b */
5523 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5525 pic16_emitcode("mov","b,%s",l);
5526 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5527 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5532 if(result && preserve_result)
5535 for(i = 0; i < AOP_SIZE(result); i++)
5536 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5539 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5541 if(result && preserve_result)
5542 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5545 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5547 pic16_emitpLabel(lbl->key);
5549 if(result && preserve_result)
5552 for(i = 0; i < AOP_SIZE(result); i++)
5553 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5555 pic16_emitpLabel(lbl_done->key);
5558 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5566 /*-----------------------------------------------------------------*/
5567 /* gencjne - compare and jump if not equal */
5568 /*-----------------------------------------------------------------*/
5569 static void gencjne(operand *left, operand *right, iCode *ifx)
5571 symbol *tlbl = newiTempLabel(NULL);
5573 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5574 gencjneshort(left, right, lbl);
5576 pic16_emitcode("mov","a,%s",one);
5577 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5578 pic16_emitcode("","%05d_DS_:",lbl->key+100);
5579 pic16_emitcode("clr","a");
5580 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5582 pic16_emitpLabel(lbl->key);
5583 pic16_emitpLabel(tlbl->key);
5589 /*-----------------------------------------------------------------*/
5590 /* is_LitOp - check if operand has to be treated as literal */
5591 /*-----------------------------------------------------------------*/
5592 static bool is_LitOp(operand *op)
5594 return (AOP_TYPE(op) == AOP_LIT)
5595 || ( (AOP_TYPE(op) == AOP_PCODE)
5596 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5597 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));
5600 /*-----------------------------------------------------------------*/
5601 /* is_LitAOp - check if operand has to be treated as literal */
5602 /*-----------------------------------------------------------------*/
5603 static bool is_LitAOp(asmop *aop)
5605 return (aop->type == AOP_LIT)
5606 || ( (aop->type == AOP_PCODE)
5607 && ( (aop->aopu.pcop->type == PO_LITERAL)
5608 || (aop->aopu.pcop->type == PO_IMMEDIATE) ));
5613 /*-----------------------------------------------------------------*/
5614 /* genCmpEq - generates code for equal to */
5615 /*-----------------------------------------------------------------*/
5616 static void genCmpEq (iCode *ic, iCode *ifx)
5618 operand *left, *right, *result;
5619 symbol *falselbl = newiTempLabel(NULL);
5620 symbol *donelbl = newiTempLabel(NULL);
5622 int preserve_result = 0;
5623 int generate_result = 0;
5626 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5627 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5628 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5630 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5631 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5633 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5635 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5636 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5640 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5642 operand *tmp = right ;
5647 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5648 preserve_result = 1;
5650 if(result && AOP_SIZE(result))
5651 generate_result = 1;
5653 if(generate_result && !preserve_result)
5655 for(i = 0; i < AOP_SIZE(result); i++)
5656 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5659 for(i=0; i < AOP_SIZE(left); i++)
5661 if(AOP_TYPE(left) != AOP_ACC)
5664 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5666 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5669 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
5671 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
5673 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5678 if(generate_result && preserve_result)
5680 for(i = 0; i < AOP_SIZE(result); i++)
5681 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5685 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5687 if(generate_result && preserve_result)
5688 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5690 if(ifx && IC_TRUE(ifx))
5691 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5693 if(ifx && IC_FALSE(ifx))
5694 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5696 pic16_emitpLabel(falselbl->key);
5700 if(ifx && IC_FALSE(ifx))
5701 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5703 if(generate_result && preserve_result)
5705 for(i = 0; i < AOP_SIZE(result); i++)
5706 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5709 pic16_emitpLabel(donelbl->key);
5715 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5716 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5717 pic16_freeAsmop(result,NULL,ic,TRUE);
5723 // old version kept for reference
5725 /*-----------------------------------------------------------------*/
5726 /* genCmpEq - generates code for equal to */
5727 /*-----------------------------------------------------------------*/
5728 static void genCmpEq (iCode *ic, iCode *ifx)
5730 operand *left, *right, *result;
5731 unsigned long lit = 0L;
5733 symbol *falselbl = newiTempLabel(NULL);
5736 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5739 DEBUGpic16_emitcode ("; ifx is non-null","");
5741 DEBUGpic16_emitcode ("; ifx is null","");
5743 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5744 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5745 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5747 size = max(AOP_SIZE(left),AOP_SIZE(right));
5749 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5751 /* if literal, literal on the right or
5752 if the right is in a pointer register and left
5754 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
5755 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5756 operand *tmp = right ;
5762 if(ifx && !AOP_SIZE(result)){
5764 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
5765 /* if they are both bit variables */
5766 if (AOP_TYPE(left) == AOP_CRY &&
5767 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5768 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
5769 if(AOP_TYPE(right) == AOP_LIT){
5770 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5772 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5773 pic16_emitcode("cpl","c");
5774 } else if(lit == 1L) {
5775 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5777 pic16_emitcode("clr","c");
5779 /* AOP_TYPE(right) == AOP_CRY */
5781 symbol *lbl = newiTempLabel(NULL);
5782 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5783 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5784 pic16_emitcode("cpl","c");
5785 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5787 /* if true label then we jump if condition
5789 tlbl = newiTempLabel(NULL);
5790 if ( IC_TRUE(ifx) ) {
5791 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5792 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5794 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5795 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5797 pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5800 /* left and right are both bit variables, result is carry */
5803 resolveIfx(&rIfx,ifx);
5805 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5806 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5807 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5808 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5813 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
5815 /* They're not both bit variables. Is the right a literal? */
5816 if(AOP_TYPE(right) == AOP_LIT) {
5817 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5822 switch(lit & 0xff) {
5824 if ( IC_TRUE(ifx) ) {
5825 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5827 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5829 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5830 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5834 if ( IC_TRUE(ifx) ) {
5835 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5837 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5839 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5840 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5844 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5846 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5851 /* end of size == 1 */
5855 genc16bit2lit(left,lit,offset);
5858 /* end of size == 2 */
5863 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5864 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5865 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5866 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5869 /* search for patterns that can be optimized */
5871 genc16bit2lit(left,lit,0);
5875 emitSKPZ; // if hi word unequal
5877 emitSKPNZ; // if hi word equal
5879 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5880 genc16bit2lit(left,lit,2);
5883 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5884 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5888 pic16_emitpLabel(falselbl->key);
5897 } else if(AOP_TYPE(right) == AOP_CRY ) {
5898 /* we know the left is not a bit, but that the right is */
5899 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5900 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5901 pic16_popGet(AOP(right),offset));
5902 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5904 /* if the two are equal, then W will be 0 and the Z bit is set
5905 * we could test Z now, or go ahead and check the high order bytes if
5906 * the variable we're comparing is larger than a byte. */
5909 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5911 if ( IC_TRUE(ifx) ) {
5913 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5914 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5917 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5918 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5922 /* They're both variables that are larger than bits */
5925 tlbl = newiTempLabel(NULL);
5928 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5929 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5931 if ( IC_TRUE(ifx) ) {
5935 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5937 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5938 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5942 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5945 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5946 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5951 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5953 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5954 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5958 if(s>1 && IC_TRUE(ifx)) {
5959 pic16_emitpLabel(tlbl->key);
5960 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
5964 /* mark the icode as generated */
5969 /* if they are both bit variables */
5970 if (AOP_TYPE(left) == AOP_CRY &&
5971 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5972 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
5973 if(AOP_TYPE(right) == AOP_LIT){
5974 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5976 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5977 pic16_emitcode("cpl","c");
5978 } else if(lit == 1L) {
5979 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5981 pic16_emitcode("clr","c");
5983 /* AOP_TYPE(right) == AOP_CRY */
5985 symbol *lbl = newiTempLabel(NULL);
5986 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5987 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5988 pic16_emitcode("cpl","c");
5989 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5992 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5993 pic16_outBitC(result);
5997 genIfxJump (ifx,"c");
6000 /* if the result is used in an arithmetic operation
6001 then put the result in place */
6002 pic16_outBitC(result);
6005 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
6006 gencjne(left,right,result,ifx);
6009 gencjne(left,right,newiTempLabel(NULL));
6011 if(IC_TRUE(ifx)->key)
6012 gencjne(left,right,IC_TRUE(ifx)->key);
6014 gencjne(left,right,IC_FALSE(ifx)->key);
6018 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6019 pic16_aopPut(AOP(result),"a",0);
6024 genIfxJump (ifx,"a");
6028 /* if the result is used in an arithmetic operation
6029 then put the result in place */
6031 if (AOP_TYPE(result) != AOP_CRY)
6032 pic16_outAcc(result);
6034 /* leave the result in acc */
6038 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6039 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6040 pic16_freeAsmop(result,NULL,ic,TRUE);
6044 /*-----------------------------------------------------------------*/
6045 /* ifxForOp - returns the icode containing the ifx for operand */
6046 /*-----------------------------------------------------------------*/
6047 static iCode *ifxForOp ( operand *op, iCode *ic )
6049 /* if true symbol then needs to be assigned */
6050 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6051 if (IS_TRUE_SYMOP(op))
6054 /* if this has register type condition and
6055 the next instruction is ifx with the same operand
6056 and live to of the operand is upto the ifx only then */
6058 && ic->next->op == IFX
6059 && IC_COND(ic->next)->key == op->key
6060 && OP_SYMBOL(op)->liveTo <= ic->next->seq
6062 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6067 ic->next->op == IFX &&
6068 IC_COND(ic->next)->key == op->key) {
6069 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6073 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6075 ic->next->op == IFX)
6076 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6079 ic->next->op == IFX &&
6080 IC_COND(ic->next)->key == op->key) {
6081 DEBUGpic16_emitcode ("; "," key is okay");
6082 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6083 OP_SYMBOL(op)->liveTo,
6088 /* the code below is completely untested
6089 * it just allows ulong2fs.c compile -- VR */
6092 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6093 __FILE__, __FUNCTION__, __LINE__);
6095 /* if this has register type condition and
6096 the next instruction is ifx with the same operand
6097 and live to of the operand is upto the ifx only then */
6099 ic->next->op == IFX &&
6100 IC_COND(ic->next)->key == op->key &&
6101 OP_SYMBOL(op)->liveTo <= ic->next->seq )
6105 ic->next->op == IFX &&
6106 IC_COND(ic->next)->key == op->key) {
6107 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6111 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6112 __FILE__, __FUNCTION__, __LINE__);
6114 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
6119 /*-----------------------------------------------------------------*/
6120 /* genAndOp - for && operation */
6121 /*-----------------------------------------------------------------*/
6122 static void genAndOp (iCode *ic)
6124 operand *left,*right, *result;
6127 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6128 /* note here that && operations that are in an
6129 if statement are taken away by backPatchLabels
6130 only those used in arthmetic operations remain */
6131 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6132 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6133 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6135 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6137 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6138 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6139 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6141 /* if both are bit variables */
6142 /* if (AOP_TYPE(left) == AOP_CRY && */
6143 /* AOP_TYPE(right) == AOP_CRY ) { */
6144 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6145 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6146 /* pic16_outBitC(result); */
6148 /* tlbl = newiTempLabel(NULL); */
6149 /* pic16_toBoolean(left); */
6150 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6151 /* pic16_toBoolean(right); */
6152 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6153 /* pic16_outBitAcc(result); */
6156 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6157 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6158 pic16_freeAsmop(result,NULL,ic,TRUE);
6162 /*-----------------------------------------------------------------*/
6163 /* genOrOp - for || operation */
6164 /*-----------------------------------------------------------------*/
6167 modified this code, but it doesn't appear to ever get called
6170 static void genOrOp (iCode *ic)
6172 operand *left,*right, *result;
6175 /* note here that || operations that are in an
6176 if statement are taken away by backPatchLabels
6177 only those used in arthmetic operations remain */
6178 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6179 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6180 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6181 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6183 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6185 /* if both are bit variables */
6186 if (AOP_TYPE(left) == AOP_CRY &&
6187 AOP_TYPE(right) == AOP_CRY ) {
6188 pic16_emitcode("clrc","");
6189 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6190 AOP(left)->aopu.aop_dir,
6191 AOP(left)->aopu.aop_dir);
6192 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6193 AOP(right)->aopu.aop_dir,
6194 AOP(right)->aopu.aop_dir);
6195 pic16_emitcode("setc","");
6198 tlbl = newiTempLabel(NULL);
6199 pic16_toBoolean(left);
6201 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
6202 pic16_toBoolean(right);
6203 pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
6205 pic16_outBitAcc(result);
6208 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6209 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6210 pic16_freeAsmop(result,NULL,ic,TRUE);
6213 /*-----------------------------------------------------------------*/
6214 /* isLiteralBit - test if lit == 2^n */
6215 /*-----------------------------------------------------------------*/
6216 static int isLiteralBit(unsigned long lit)
6218 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6219 0x100L,0x200L,0x400L,0x800L,
6220 0x1000L,0x2000L,0x4000L,0x8000L,
6221 0x10000L,0x20000L,0x40000L,0x80000L,
6222 0x100000L,0x200000L,0x400000L,0x800000L,
6223 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6224 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6227 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6228 for(idx = 0; idx < 32; idx++)
6234 /*-----------------------------------------------------------------*/
6235 /* continueIfTrue - */
6236 /*-----------------------------------------------------------------*/
6237 static void continueIfTrue (iCode *ic)
6239 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6241 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6245 /*-----------------------------------------------------------------*/
6247 /*-----------------------------------------------------------------*/
6248 static void jumpIfTrue (iCode *ic)
6250 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6252 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6256 /*-----------------------------------------------------------------*/
6257 /* jmpTrueOrFalse - */
6258 /*-----------------------------------------------------------------*/
6259 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6261 // ugly but optimized by peephole
6262 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6264 symbol *nlbl = newiTempLabel(NULL);
6265 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
6266 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6267 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6268 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6271 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6272 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6277 /*-----------------------------------------------------------------*/
6278 /* genAnd - code for and */
6279 /*-----------------------------------------------------------------*/
6280 static void genAnd (iCode *ic, iCode *ifx)
6282 operand *left, *right, *result;
6284 unsigned long lit = 0L;
6289 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6290 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6291 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6292 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6294 resolveIfx(&rIfx,ifx);
6296 /* if left is a literal & right is not then exchange them */
6297 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6298 AOP_NEEDSACC(left)) {
6299 operand *tmp = right ;
6304 /* if result = right then exchange them */
6305 if(pic16_sameRegs(AOP(result),AOP(right))){
6306 operand *tmp = right ;
6311 /* if right is bit then exchange them */
6312 if (AOP_TYPE(right) == AOP_CRY &&
6313 AOP_TYPE(left) != AOP_CRY){
6314 operand *tmp = right ;
6318 if(AOP_TYPE(right) == AOP_LIT)
6319 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6321 size = AOP_SIZE(result);
6323 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6326 // result = bit & yy;
6327 if (AOP_TYPE(left) == AOP_CRY){
6328 // c = bit & literal;
6329 if(AOP_TYPE(right) == AOP_LIT){
6331 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6334 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6337 if(size && (AOP_TYPE(result) == AOP_CRY)){
6338 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6341 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6345 pic16_emitcode("clr","c");
6348 if (AOP_TYPE(right) == AOP_CRY){
6350 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6351 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6354 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6356 pic16_emitcode("rrc","a");
6357 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6363 pic16_outBitC(result);
6365 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6366 genIfxJump(ifx, "c");
6370 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6371 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6372 if((AOP_TYPE(right) == AOP_LIT) &&
6373 (AOP_TYPE(result) == AOP_CRY) &&
6374 (AOP_TYPE(left) != AOP_CRY)){
6375 int posbit = isLiteralBit(lit);
6379 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6382 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6388 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6389 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6391 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6392 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6395 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6396 size = AOP_SIZE(left);
6399 int bp = posbit, ofs=0;
6406 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6407 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0));
6411 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6412 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6414 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6421 symbol *tlbl = newiTempLabel(NULL);
6422 int sizel = AOP_SIZE(left);
6424 pic16_emitcode("setb","c");
6426 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6427 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6429 if((posbit = isLiteralBit(bytelit)) != 0)
6430 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6432 if(bytelit != 0x0FFL)
6433 pic16_emitcode("anl","a,%s",
6434 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6435 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6440 // bit = left & literal
6442 pic16_emitcode("clr","c");
6443 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6445 // if(left & literal)
6448 jmpTrueOrFalse(ifx, tlbl);
6452 pic16_outBitC(result);
6456 /* if left is same as result */
6457 if(pic16_sameRegs(AOP(result),AOP(left))){
6459 for(;size--; offset++,lit>>=8) {
6460 if(AOP_TYPE(right) == AOP_LIT){
6461 switch(lit & 0xff) {
6463 /* and'ing with 0 has clears the result */
6464 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6465 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6468 /* and'ing with 0xff is a nop when the result and left are the same */
6473 int p = my_powof2( (~lit) & 0xff );
6475 /* only one bit is set in the literal, so use a bcf instruction */
6476 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6477 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6480 pic16_emitcode("movlw","0x%x", (lit & 0xff));
6481 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6482 if(know_W != (lit&0xff))
6483 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6485 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6490 if (AOP_TYPE(left) == AOP_ACC) {
6491 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6493 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6494 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6501 // left & result in different registers
6502 if(AOP_TYPE(result) == AOP_CRY){
6504 // if(size), result in bit
6505 // if(!size && ifx), conditional oper: if(left & right)
6506 symbol *tlbl = newiTempLabel(NULL);
6507 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6509 pic16_emitcode("setb","c");
6511 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6512 pic16_emitcode("anl","a,%s",
6513 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6514 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6519 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6520 pic16_outBitC(result);
6522 jmpTrueOrFalse(ifx, tlbl);
6524 for(;(size--);offset++) {
6526 // result = left & right
6527 if(AOP_TYPE(right) == AOP_LIT){
6528 int t = (lit >> (offset*8)) & 0x0FFL;
6531 pic16_emitcode("clrf","%s",
6532 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6533 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6536 pic16_emitcode("movf","%s,w",
6537 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6538 pic16_emitcode("movwf","%s",
6539 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6540 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6541 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6544 pic16_emitcode("movlw","0x%x",t);
6545 pic16_emitcode("andwf","%s,w",
6546 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6547 pic16_emitcode("movwf","%s",
6548 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6550 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6551 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6552 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6557 if (AOP_TYPE(left) == AOP_ACC) {
6558 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6559 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6561 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6562 pic16_emitcode("andwf","%s,w",
6563 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6564 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6565 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6567 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6568 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6574 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6575 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6576 pic16_freeAsmop(result,NULL,ic,TRUE);
6579 /*-----------------------------------------------------------------*/
6580 /* genOr - code for or */
6581 /*-----------------------------------------------------------------*/
6582 static void genOr (iCode *ic, iCode *ifx)
6584 operand *left, *right, *result;
6586 unsigned long lit = 0L;
6588 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6590 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6591 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6592 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6594 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6596 /* if left is a literal & right is not then exchange them */
6597 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6598 AOP_NEEDSACC(left)) {
6599 operand *tmp = right ;
6604 /* if result = right then exchange them */
6605 if(pic16_sameRegs(AOP(result),AOP(right))){
6606 operand *tmp = right ;
6611 /* if right is bit then exchange them */
6612 if (AOP_TYPE(right) == AOP_CRY &&
6613 AOP_TYPE(left) != AOP_CRY){
6614 operand *tmp = right ;
6619 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6621 if(AOP_TYPE(right) == AOP_LIT)
6622 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6624 size = AOP_SIZE(result);
6628 if (AOP_TYPE(left) == AOP_CRY){
6629 if(AOP_TYPE(right) == AOP_LIT){
6630 // c = bit & literal;
6632 // lit != 0 => result = 1
6633 if(AOP_TYPE(result) == AOP_CRY){
6635 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6636 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6637 // AOP(result)->aopu.aop_dir,
6638 // AOP(result)->aopu.aop_dir);
6640 continueIfTrue(ifx);
6644 // lit == 0 => result = left
6645 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6647 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6650 if (AOP_TYPE(right) == AOP_CRY){
6651 if(pic16_sameRegs(AOP(result),AOP(left))){
6653 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6654 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6655 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6657 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6658 AOP(result)->aopu.aop_dir,
6659 AOP(result)->aopu.aop_dir);
6660 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6661 AOP(right)->aopu.aop_dir,
6662 AOP(right)->aopu.aop_dir);
6663 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6664 AOP(result)->aopu.aop_dir,
6665 AOP(result)->aopu.aop_dir);
6667 if( AOP_TYPE(result) == AOP_ACC) {
6668 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6669 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6670 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6671 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6675 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6676 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6677 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6678 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6680 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6681 AOP(result)->aopu.aop_dir,
6682 AOP(result)->aopu.aop_dir);
6683 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6684 AOP(right)->aopu.aop_dir,
6685 AOP(right)->aopu.aop_dir);
6686 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6687 AOP(left)->aopu.aop_dir,
6688 AOP(left)->aopu.aop_dir);
6689 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6690 AOP(result)->aopu.aop_dir,
6691 AOP(result)->aopu.aop_dir);
6696 symbol *tlbl = newiTempLabel(NULL);
6697 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6700 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6701 if( AOP_TYPE(right) == AOP_ACC) {
6702 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6704 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6705 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6710 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6711 pic16_emitcode(";XXX setb","c");
6712 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6713 AOP(left)->aopu.aop_dir,tlbl->key+100);
6714 pic16_toBoolean(right);
6715 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6716 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6717 jmpTrueOrFalse(ifx, tlbl);
6721 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6728 pic16_outBitC(result);
6730 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6731 genIfxJump(ifx, "c");
6735 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6736 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6737 if((AOP_TYPE(right) == AOP_LIT) &&
6738 (AOP_TYPE(result) == AOP_CRY) &&
6739 (AOP_TYPE(left) != AOP_CRY)){
6741 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6744 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6746 continueIfTrue(ifx);
6749 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6750 // lit = 0, result = boolean(left)
6752 pic16_emitcode(";XXX setb","c");
6753 pic16_toBoolean(right);
6755 symbol *tlbl = newiTempLabel(NULL);
6756 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6758 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6760 genIfxJump (ifx,"a");
6764 pic16_outBitC(result);
6768 /* if left is same as result */
6769 if(pic16_sameRegs(AOP(result),AOP(left))){
6771 for(;size--; offset++,lit>>=8) {
6772 if(AOP_TYPE(right) == AOP_LIT){
6773 if((lit & 0xff) == 0)
6774 /* or'ing with 0 has no effect */
6777 int p = my_powof2(lit & 0xff);
6779 /* only one bit is set in the literal, so use a bsf instruction */
6780 pic16_emitpcode(POC_BSF,
6781 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6783 if(know_W != (lit & 0xff))
6784 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6785 know_W = lit & 0xff;
6786 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6791 if (AOP_TYPE(left) == AOP_ACC) {
6792 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
6793 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6795 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6796 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6798 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6799 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6805 // left & result in different registers
6806 if(AOP_TYPE(result) == AOP_CRY){
6808 // if(size), result in bit
6809 // if(!size && ifx), conditional oper: if(left | right)
6810 symbol *tlbl = newiTempLabel(NULL);
6811 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6812 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6816 pic16_emitcode(";XXX setb","c");
6818 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6819 pic16_emitcode(";XXX orl","a,%s",
6820 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6821 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6826 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6827 pic16_outBitC(result);
6829 jmpTrueOrFalse(ifx, tlbl);
6830 } else for(;(size--);offset++){
6832 // result = left & right
6833 if(AOP_TYPE(right) == AOP_LIT){
6834 int t = (lit >> (offset*8)) & 0x0FFL;
6837 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
6838 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6840 pic16_emitcode("movf","%s,w",
6841 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6842 pic16_emitcode("movwf","%s",
6843 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6846 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6847 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6848 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6850 pic16_emitcode("movlw","0x%x",t);
6851 pic16_emitcode("iorwf","%s,w",
6852 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6853 pic16_emitcode("movwf","%s",
6854 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6860 // faster than result <- left, anl result,right
6861 // and better if result is SFR
6862 if (AOP_TYPE(left) == AOP_ACC) {
6863 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
6864 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6866 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6867 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6869 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6870 pic16_emitcode("iorwf","%s,w",
6871 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6873 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6874 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6879 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6880 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6881 pic16_freeAsmop(result,NULL,ic,TRUE);
6884 /*-----------------------------------------------------------------*/
6885 /* genXor - code for xclusive or */
6886 /*-----------------------------------------------------------------*/
6887 static void genXor (iCode *ic, iCode *ifx)
6889 operand *left, *right, *result;
6891 unsigned long lit = 0L;
6893 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6895 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6896 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6897 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6899 /* if left is a literal & right is not ||
6900 if left needs acc & right does not */
6901 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6902 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6903 operand *tmp = right ;
6908 /* if result = right then exchange them */
6909 if(pic16_sameRegs(AOP(result),AOP(right))){
6910 operand *tmp = right ;
6915 /* if right is bit then exchange them */
6916 if (AOP_TYPE(right) == AOP_CRY &&
6917 AOP_TYPE(left) != AOP_CRY){
6918 operand *tmp = right ;
6922 if(AOP_TYPE(right) == AOP_LIT)
6923 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6925 size = AOP_SIZE(result);
6929 if (AOP_TYPE(left) == AOP_CRY){
6930 if(AOP_TYPE(right) == AOP_LIT){
6931 // c = bit & literal;
6933 // lit>>1 != 0 => result = 1
6934 if(AOP_TYPE(result) == AOP_CRY){
6936 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
6937 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6939 continueIfTrue(ifx);
6942 pic16_emitcode("setb","c");
6946 // lit == 0, result = left
6947 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6949 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6951 // lit == 1, result = not(left)
6952 if(size && pic16_sameRegs(AOP(result),AOP(left))){
6953 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
6954 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
6955 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6958 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6959 pic16_emitcode("cpl","c");
6966 symbol *tlbl = newiTempLabel(NULL);
6967 if (AOP_TYPE(right) == AOP_CRY){
6969 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6972 int sizer = AOP_SIZE(right);
6974 // if val>>1 != 0, result = 1
6975 pic16_emitcode("setb","c");
6977 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6979 // test the msb of the lsb
6980 pic16_emitcode("anl","a,#0xfe");
6981 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6985 pic16_emitcode("rrc","a");
6987 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6988 pic16_emitcode("cpl","c");
6989 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6994 pic16_outBitC(result);
6996 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6997 genIfxJump(ifx, "c");
7001 if(pic16_sameRegs(AOP(result),AOP(left))){
7002 /* if left is same as result */
7003 for(;size--; offset++) {
7004 if(AOP_TYPE(right) == AOP_LIT){
7005 int t = (lit >> (offset*8)) & 0x0FFL;
7009 if (IS_AOP_PREG(left)) {
7010 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7011 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7012 pic16_aopPut(AOP(result),"a",offset);
7014 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7015 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7016 pic16_emitcode("xrl","%s,%s",
7017 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7018 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7021 if (AOP_TYPE(left) == AOP_ACC)
7022 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7024 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7025 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7027 if (IS_AOP_PREG(left)) {
7028 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7029 pic16_aopPut(AOP(result),"a",offset);
7031 pic16_emitcode("xrl","%s,a",
7032 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7038 // left & result in different registers
7039 if(AOP_TYPE(result) == AOP_CRY){
7041 // if(size), result in bit
7042 // if(!size && ifx), conditional oper: if(left ^ right)
7043 symbol *tlbl = newiTempLabel(NULL);
7044 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7046 pic16_emitcode("setb","c");
7048 if((AOP_TYPE(right) == AOP_LIT) &&
7049 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7050 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7052 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7053 pic16_emitcode("xrl","a,%s",
7054 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7056 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7061 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7062 pic16_outBitC(result);
7064 jmpTrueOrFalse(ifx, tlbl);
7065 } else for(;(size--);offset++){
7067 // result = left & right
7068 if(AOP_TYPE(right) == AOP_LIT){
7069 int t = (lit >> (offset*8)) & 0x0FFL;
7072 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7073 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7074 pic16_emitcode("movf","%s,w",
7075 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7076 pic16_emitcode("movwf","%s",
7077 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7080 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7081 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7082 pic16_emitcode("comf","%s,w",
7083 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7084 pic16_emitcode("movwf","%s",
7085 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7088 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7089 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7090 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7091 pic16_emitcode("movlw","0x%x",t);
7092 pic16_emitcode("xorwf","%s,w",
7093 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7094 pic16_emitcode("movwf","%s",
7095 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7101 // faster than result <- left, anl result,right
7102 // and better if result is SFR
7103 if (AOP_TYPE(left) == AOP_ACC) {
7104 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7105 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7107 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7108 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7109 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7110 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7112 if ( AOP_TYPE(result) != AOP_ACC){
7113 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7114 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7120 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7121 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7122 pic16_freeAsmop(result,NULL,ic,TRUE);
7125 /*-----------------------------------------------------------------*/
7126 /* genInline - write the inline code out */
7127 /*-----------------------------------------------------------------*/
7128 static void genInline (iCode *ic)
7130 char *buffer, *bp, *bp1;
7132 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7134 _G.inLine += (!options.asmpeep);
7136 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7137 strcpy(buffer,IC_INLINE(ic));
7139 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7141 /* emit each line as a code */
7147 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7155 /* print label, use this special format with NULL directive
7156 * to denote that the argument should not be indented with tab */
7157 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7164 if ((bp1 != bp) && *bp1)
7165 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7170 _G.inLine -= (!options.asmpeep);
7173 /*-----------------------------------------------------------------*/
7174 /* genRRC - rotate right with carry */
7175 /*-----------------------------------------------------------------*/
7176 static void genRRC (iCode *ic)
7178 operand *left , *result ;
7179 int size, offset = 0, same;
7181 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7183 /* rotate right with carry */
7185 result=IC_RESULT(ic);
7186 pic16_aopOp (left,ic,FALSE);
7187 pic16_aopOp (result,ic,FALSE);
7189 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7191 same = pic16_sameRegs(AOP(result),AOP(left));
7193 size = AOP_SIZE(result);
7195 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7197 /* get the lsb and put it into the carry */
7198 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7205 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7207 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7208 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7214 pic16_freeAsmop(left,NULL,ic,TRUE);
7215 pic16_freeAsmop(result,NULL,ic,TRUE);
7218 /*-----------------------------------------------------------------*/
7219 /* genRLC - generate code for rotate left with carry */
7220 /*-----------------------------------------------------------------*/
7221 static void genRLC (iCode *ic)
7223 operand *left , *result ;
7224 int size, offset = 0;
7227 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7228 /* rotate right with carry */
7230 result=IC_RESULT(ic);
7231 pic16_aopOp (left,ic,FALSE);
7232 pic16_aopOp (result,ic,FALSE);
7234 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7236 same = pic16_sameRegs(AOP(result),AOP(left));
7238 /* move it to the result */
7239 size = AOP_SIZE(result);
7241 /* get the msb and put it into the carry */
7242 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7249 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7251 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7252 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7259 pic16_freeAsmop(left,NULL,ic,TRUE);
7260 pic16_freeAsmop(result,NULL,ic,TRUE);
7264 /* gpasm can get the highest order bit with HIGH/UPPER
7265 * so the following probably is not needed -- VR */
7267 /*-----------------------------------------------------------------*/
7268 /* genGetHbit - generates code get highest order bit */
7269 /*-----------------------------------------------------------------*/
7270 static void genGetHbit (iCode *ic)
7272 operand *left, *result;
7274 result=IC_RESULT(ic);
7275 pic16_aopOp (left,ic,FALSE);
7276 pic16_aopOp (result,ic,FALSE);
7278 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7279 /* get the highest order byte into a */
7280 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7281 if(AOP_TYPE(result) == AOP_CRY){
7282 pic16_emitcode("rlc","a");
7283 pic16_outBitC(result);
7286 pic16_emitcode("rl","a");
7287 pic16_emitcode("anl","a,#0x01");
7288 pic16_outAcc(result);
7292 pic16_freeAsmop(left,NULL,ic,TRUE);
7293 pic16_freeAsmop(result,NULL,ic,TRUE);
7297 /*-----------------------------------------------------------------*/
7298 /* AccRol - rotate left accumulator by known count */
7299 /*-----------------------------------------------------------------*/
7300 static void AccRol (int shCount)
7302 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7303 shCount &= 0x0007; // shCount : 0..7
7308 pic16_emitcode("rl","a");
7311 pic16_emitcode("rl","a");
7312 pic16_emitcode("rl","a");
7315 pic16_emitcode("swap","a");
7316 pic16_emitcode("rr","a");
7319 pic16_emitcode("swap","a");
7322 pic16_emitcode("swap","a");
7323 pic16_emitcode("rl","a");
7326 pic16_emitcode("rr","a");
7327 pic16_emitcode("rr","a");
7330 pic16_emitcode("rr","a");
7336 /*-----------------------------------------------------------------*/
7337 /* AccLsh - left shift accumulator by known count */
7338 /*-----------------------------------------------------------------*/
7339 static void AccLsh (int shCount)
7341 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7347 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7350 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7351 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7354 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7355 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7358 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7361 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7362 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7365 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7366 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7369 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7373 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7376 /*-----------------------------------------------------------------*/
7377 /* AccRsh - right shift accumulator by known count */
7378 /*-----------------------------------------------------------------*/
7379 static void AccRsh (int shCount, int andmask)
7381 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7386 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7387 // andmask = 0; /* no need */
7390 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7391 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7392 // andmask = 0; /* no need */
7395 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7396 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7399 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7402 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7403 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7406 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7407 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7410 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7415 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7417 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7421 /*-----------------------------------------------------------------*/
7422 /* AccSRsh - signed right shift accumulator by known count */
7423 /*-----------------------------------------------------------------*/
7424 static void AccSRsh (int shCount)
7427 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7430 pic16_emitcode("mov","c,acc.7");
7431 pic16_emitcode("rrc","a");
7432 } else if(shCount == 2){
7433 pic16_emitcode("mov","c,acc.7");
7434 pic16_emitcode("rrc","a");
7435 pic16_emitcode("mov","c,acc.7");
7436 pic16_emitcode("rrc","a");
7438 tlbl = newiTempLabel(NULL);
7439 /* rotate right accumulator */
7440 AccRol(8 - shCount);
7441 /* and kill the higher order bits */
7442 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7443 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7444 pic16_emitcode("orl","a,#0x%02x",
7445 (unsigned char)~SRMask[shCount]);
7446 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7451 /*-----------------------------------------------------------------*/
7452 /* shiftR1Left2Result - shift right one byte from left to result */
7453 /*-----------------------------------------------------------------*/
7454 static void shiftR1Left2ResultSigned (operand *left, int offl,
7455 operand *result, int offr,
7460 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7462 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7466 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7468 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7470 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7471 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7477 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7479 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7481 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7482 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7484 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7485 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7491 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7493 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7494 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7497 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7498 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7499 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7501 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7502 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7504 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7508 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7509 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7510 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7511 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
7512 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7516 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7518 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7519 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7521 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7522 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
7523 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7524 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
7525 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7530 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7531 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7532 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7533 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7534 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7535 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7537 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7538 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7539 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7540 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7541 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7547 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7548 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7549 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7550 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7552 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7553 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7554 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7562 /*-----------------------------------------------------------------*/
7563 /* shiftR1Left2Result - shift right one byte from left to result */
7564 /*-----------------------------------------------------------------*/
7565 static void shiftR1Left2Result (operand *left, int offl,
7566 operand *result, int offr,
7567 int shCount, int sign)
7571 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7573 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7575 /* Copy the msb into the carry if signed. */
7577 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7587 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7589 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7590 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7596 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7598 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7599 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7602 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7607 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7609 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7610 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7613 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7614 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7615 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7616 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7620 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7621 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7622 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7626 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7627 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7628 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7630 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7635 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7636 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7637 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7638 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7639 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7644 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7645 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7646 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7655 /*-----------------------------------------------------------------*/
7656 /* shiftL1Left2Result - shift left one byte from left to result */
7657 /*-----------------------------------------------------------------*/
7658 static void shiftL1Left2Result (operand *left, int offl,
7659 operand *result, int offr, int shCount)
7664 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7666 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7667 DEBUGpic16_emitcode ("; ***","same = %d",same);
7668 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7670 /* shift left accumulator */
7671 //AccLsh(shCount); // don't comment out just yet...
7672 // pic16_aopPut(AOP(result),"a",offr);
7676 /* Shift left 1 bit position */
7677 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7679 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7681 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7682 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7686 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7687 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7688 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7689 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7692 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7693 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7694 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7695 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7696 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7699 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7700 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7701 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7704 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7705 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7706 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7707 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7710 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7711 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7712 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7713 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7714 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7717 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7718 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7719 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7723 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7728 /*-----------------------------------------------------------------*/
7729 /* movLeft2Result - move byte from left to result */
7730 /*-----------------------------------------------------------------*/
7731 static void movLeft2Result (operand *left, int offl,
7732 operand *result, int offr)
7735 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7736 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7737 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7739 if (*l == '@' && (IS_AOP_PREG(result))) {
7740 pic16_emitcode("mov","a,%s",l);
7741 pic16_aopPut(AOP(result),"a",offr);
7743 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7744 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7749 /*-----------------------------------------------------------------*/
7750 /* shiftL2Left2Result - shift left two bytes from left to result */
7751 /*-----------------------------------------------------------------*/
7752 static void shiftL2Left2Result (operand *left, int offl,
7753 operand *result, int offr, int shCount)
7755 int same = pic16_sameRegs(AOP(result), AOP(left));
7758 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7760 if (same && (offl != offr)) { // shift bytes
7763 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7764 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7766 } else { // just treat as different later on
7779 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7780 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7781 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7785 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7786 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7792 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7793 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7794 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7795 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7796 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7797 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7798 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7800 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7801 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7805 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7806 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7807 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7808 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7809 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7810 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7811 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7812 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7813 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7814 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7817 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7818 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7819 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7820 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7821 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7831 /* note, use a mov/add for the shift since the mov has a
7832 chance of getting optimized out */
7833 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7834 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7835 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7836 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7837 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7841 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7842 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7848 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7849 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7850 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7851 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7852 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7853 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7854 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7855 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7859 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7860 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7864 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7865 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7866 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7867 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7869 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7870 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7871 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7872 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7873 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7874 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7875 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7876 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7879 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7880 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7881 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7882 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7883 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7888 /*-----------------------------------------------------------------*/
7889 /* shiftR2Left2Result - shift right two bytes from left to result */
7890 /*-----------------------------------------------------------------*/
7891 static void shiftR2Left2Result (operand *left, int offl,
7892 operand *result, int offr,
7893 int shCount, int sign)
7895 int same = pic16_sameRegs(AOP(result), AOP(left));
7897 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7899 if (same && (offl != offr)) { // shift right bytes
7902 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7903 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7905 } else { // just treat as different later on
7917 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7922 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7923 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7925 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7926 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7927 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7928 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7933 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7936 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7937 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7944 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7945 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7946 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7948 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7949 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7950 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7951 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7953 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7954 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7955 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7957 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7958 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7959 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7960 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7961 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7965 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7966 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7970 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7971 pic16_emitpcode(POC_BTFSC,
7972 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7973 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7981 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7982 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7984 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7985 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7986 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7987 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7989 pic16_emitpcode(POC_BTFSC,
7990 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7991 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7993 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7994 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7995 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7996 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7998 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7999 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8000 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8001 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8002 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8003 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8004 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8005 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8007 pic16_emitpcode(POC_BTFSC,
8008 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
8009 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8011 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8012 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8019 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8020 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8021 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8022 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8025 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8027 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8032 /*-----------------------------------------------------------------*/
8033 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8034 /*-----------------------------------------------------------------*/
8035 static void shiftLLeftOrResult (operand *left, int offl,
8036 operand *result, int offr, int shCount)
8038 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8040 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8041 /* shift left accumulator */
8043 /* or with result */
8044 /* back to result */
8045 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8048 /*-----------------------------------------------------------------*/
8049 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8050 /*-----------------------------------------------------------------*/
8051 static void shiftRLeftOrResult (operand *left, int offl,
8052 operand *result, int offr, int shCount)
8054 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8056 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8057 /* shift right accumulator */
8059 /* or with result */
8060 /* back to result */
8061 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8064 /*-----------------------------------------------------------------*/
8065 /* genlshOne - left shift a one byte quantity by known count */
8066 /*-----------------------------------------------------------------*/
8067 static void genlshOne (operand *result, operand *left, int shCount)
8069 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8070 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8073 /*-----------------------------------------------------------------*/
8074 /* genlshTwo - left shift two bytes by known amount != 0 */
8075 /*-----------------------------------------------------------------*/
8076 static void genlshTwo (operand *result,operand *left, int shCount)
8080 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8081 size = pic16_getDataSize(result);
8083 /* if shCount >= 8 */
8089 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8091 movLeft2Result(left, LSB, result, MSB16);
8093 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8096 /* 1 <= shCount <= 7 */
8099 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8101 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8105 /*-----------------------------------------------------------------*/
8106 /* shiftLLong - shift left one long from left to result */
8107 /* offr = LSB or MSB16 */
8108 /*-----------------------------------------------------------------*/
8109 static void shiftLLong (operand *left, operand *result, int offr )
8111 int size = AOP_SIZE(result);
8112 int same = pic16_sameRegs(AOP(left),AOP(result));
8115 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8117 if (same && (offr == MSB16)) { //shift one byte
8118 for(i=size-1;i>=MSB16;i--) {
8119 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8120 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8123 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8126 if (size >= LSB+offr ){
8128 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8130 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8131 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8135 if(size >= MSB16+offr){
8137 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8139 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8140 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8144 if(size >= MSB24+offr){
8146 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8148 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8149 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8153 if(size > MSB32+offr){
8155 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8157 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8158 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8162 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8166 /*-----------------------------------------------------------------*/
8167 /* genlshFour - shift four byte by a known amount != 0 */
8168 /*-----------------------------------------------------------------*/
8169 static void genlshFour (operand *result, operand *left, int shCount)
8173 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8174 size = AOP_SIZE(result);
8176 /* if shifting more that 3 bytes */
8177 if (shCount >= 24 ) {
8180 /* lowest order of left goes to the highest
8181 order of the destination */
8182 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8184 movLeft2Result(left, LSB, result, MSB32);
8186 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8187 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8188 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8193 /* more than two bytes */
8194 else if ( shCount >= 16 ) {
8195 /* lower order two bytes goes to higher order two bytes */
8197 /* if some more remaining */
8199 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8201 movLeft2Result(left, MSB16, result, MSB32);
8202 movLeft2Result(left, LSB, result, MSB24);
8204 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8205 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8209 /* if more than 1 byte */
8210 else if ( shCount >= 8 ) {
8211 /* lower order three bytes goes to higher order three bytes */
8215 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8217 movLeft2Result(left, LSB, result, MSB16);
8219 else{ /* size = 4 */
8221 movLeft2Result(left, MSB24, result, MSB32);
8222 movLeft2Result(left, MSB16, result, MSB24);
8223 movLeft2Result(left, LSB, result, MSB16);
8224 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8226 else if(shCount == 1)
8227 shiftLLong(left, result, MSB16);
8229 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8230 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8231 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8232 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8237 /* 1 <= shCount <= 7 */
8238 else if(shCount <= 3)
8240 shiftLLong(left, result, LSB);
8241 while(--shCount >= 1)
8242 shiftLLong(result, result, LSB);
8244 /* 3 <= shCount <= 7, optimize */
8246 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8247 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8248 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8252 /*-----------------------------------------------------------------*/
8253 /* genLeftShiftLiteral - left shifting by known count */
8254 /*-----------------------------------------------------------------*/
8255 static void genLeftShiftLiteral (operand *left,
8260 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8263 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8264 pic16_freeAsmop(right,NULL,ic,TRUE);
8266 pic16_aopOp(left,ic,FALSE);
8267 pic16_aopOp(result,ic,FALSE);
8269 size = getSize(operandType(result));
8272 pic16_emitcode("; shift left ","result %d, left %d",size,
8276 /* I suppose that the left size >= result size */
8279 movLeft2Result(left, size, result, size);
8283 else if(shCount >= (size * 8))
8285 pic16_aopPut(AOP(result),zero,size);
8289 genlshOne (result,left,shCount);
8294 genlshTwo (result,left,shCount);
8298 genlshFour (result,left,shCount);
8302 pic16_freeAsmop(left,NULL,ic,TRUE);
8303 pic16_freeAsmop(result,NULL,ic,TRUE);
8306 /*-----------------------------------------------------------------*
8307 * genMultiAsm - repeat assembly instruction for size of register.
8308 * if endian == 1, then the high byte (i.e base address + size of
8309 * register) is used first else the low byte is used first;
8310 *-----------------------------------------------------------------*/
8311 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8316 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8329 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
8334 /*-----------------------------------------------------------------*/
8335 /* genLeftShift - generates code for left shifting */
8336 /*-----------------------------------------------------------------*/
8337 static void genLeftShift (iCode *ic)
8339 operand *left,*right, *result;
8342 symbol *tlbl , *tlbl1;
8345 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8347 right = IC_RIGHT(ic);
8349 result = IC_RESULT(ic);
8351 pic16_aopOp(right,ic,FALSE);
8353 /* if the shift count is known then do it
8354 as efficiently as possible */
8355 if (AOP_TYPE(right) == AOP_LIT) {
8356 genLeftShiftLiteral (left,right,result,ic);
8360 /* shift count is unknown then we have to form
8361 a loop get the loop count in B : Note: we take
8362 only the lower order byte since shifting
8363 more that 32 bits make no sense anyway, ( the
8364 largest size of an object can be only 32 bits ) */
8367 pic16_aopOp(left,ic,FALSE);
8368 pic16_aopOp(result,ic,FALSE);
8370 /* now move the left to the result if they are not the
8372 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8373 AOP_SIZE(result) > 1) {
8375 size = AOP_SIZE(result);
8378 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8379 if (*l == '@' && (IS_AOP_PREG(result))) {
8381 pic16_emitcode("mov","a,%s",l);
8382 pic16_aopPut(AOP(result),"a",offset);
8384 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8385 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8386 //pic16_aopPut(AOP(result),l,offset);
8392 size = AOP_SIZE(result);
8394 /* if it is only one byte then */
8396 if(optimized_for_speed) {
8397 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8398 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8399 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
8400 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8401 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8402 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
8403 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8404 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
8405 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
8406 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
8407 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
8408 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8411 tlbl = newiTempLabel(NULL);
8412 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8413 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8414 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8417 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8418 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8419 pic16_emitpLabel(tlbl->key);
8420 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8421 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8423 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8428 if (pic16_sameRegs(AOP(left),AOP(result))) {
8430 tlbl = newiTempLabel(NULL);
8431 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8432 genMultiAsm(POC_RRCF, result, size,1);
8433 pic16_emitpLabel(tlbl->key);
8434 genMultiAsm(POC_RLCF, result, size,0);
8435 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8437 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8441 //tlbl = newiTempLabel(NULL);
8443 //tlbl1 = newiTempLabel(NULL);
8445 //reAdjustPreg(AOP(result));
8447 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8448 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8449 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8451 //pic16_emitcode("add","a,acc");
8452 //pic16_aopPut(AOP(result),"a",offset++);
8454 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8456 // pic16_emitcode("rlc","a");
8457 // pic16_aopPut(AOP(result),"a",offset++);
8459 //reAdjustPreg(AOP(result));
8461 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8462 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8465 tlbl = newiTempLabel(NULL);
8466 tlbl1= newiTempLabel(NULL);
8468 size = AOP_SIZE(result);
8471 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8473 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8475 /* offset should be 0, 1 or 3 */
8477 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8479 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8481 pic16_emitpcode(POC_MOVWF, pctemp);
8484 pic16_emitpLabel(tlbl->key);
8487 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8489 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
8491 pic16_emitpcode(POC_DECFSZ, pctemp);
8492 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8493 pic16_emitpLabel(tlbl1->key);
8495 pic16_popReleaseTempReg(pctemp);
8499 pic16_freeAsmop (right,NULL,ic,TRUE);
8500 pic16_freeAsmop(left,NULL,ic,TRUE);
8501 pic16_freeAsmop(result,NULL,ic,TRUE);
8504 /*-----------------------------------------------------------------*/
8505 /* genrshOne - right shift a one byte quantity by known count */
8506 /*-----------------------------------------------------------------*/
8507 static void genrshOne (operand *result, operand *left,
8508 int shCount, int sign)
8510 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8511 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8514 /*-----------------------------------------------------------------*/
8515 /* genrshTwo - right shift two bytes by known amount != 0 */
8516 /*-----------------------------------------------------------------*/
8517 static void genrshTwo (operand *result,operand *left,
8518 int shCount, int sign)
8520 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8521 /* if shCount >= 8 */
8525 shiftR1Left2Result(left, MSB16, result, LSB,
8528 movLeft2Result(left, MSB16, result, LSB);
8530 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8533 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8534 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8538 /* 1 <= shCount <= 7 */
8540 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
8543 /*-----------------------------------------------------------------*/
8544 /* shiftRLong - shift right one long from left to result */
8545 /* offl = LSB or MSB16 */
8546 /*-----------------------------------------------------------------*/
8547 static void shiftRLong (operand *left, int offl,
8548 operand *result, int sign)
8550 int size = AOP_SIZE(result);
8551 int same = pic16_sameRegs(AOP(left),AOP(result));
8553 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8555 if (same && (offl == MSB16)) { //shift one byte right
8556 for(i=MSB16;i<size;i++) {
8557 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8558 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8563 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8569 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8571 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8572 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8576 /* add sign of "a" */
8577 pic16_addSign(result, MSB32, sign);
8581 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8583 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8584 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8588 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8590 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8591 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8595 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8598 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8599 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8604 /*-----------------------------------------------------------------*/
8605 /* genrshFour - shift four byte by a known amount != 0 */
8606 /*-----------------------------------------------------------------*/
8607 static void genrshFour (operand *result, operand *left,
8608 int shCount, int sign)
8610 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8611 /* if shifting more that 3 bytes */
8612 if(shCount >= 24 ) {
8615 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8617 movLeft2Result(left, MSB32, result, LSB);
8619 pic16_addSign(result, MSB16, sign);
8621 else if(shCount >= 16){
8624 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8626 movLeft2Result(left, MSB24, result, LSB);
8627 movLeft2Result(left, MSB32, result, MSB16);
8629 pic16_addSign(result, MSB24, sign);
8631 else if(shCount >= 8){
8634 shiftRLong(left, MSB16, result, sign);
8635 else if(shCount == 0){
8636 movLeft2Result(left, MSB16, result, LSB);
8637 movLeft2Result(left, MSB24, result, MSB16);
8638 movLeft2Result(left, MSB32, result, MSB24);
8639 pic16_addSign(result, MSB32, sign);
8641 else{ //shcount >= 2
8642 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8643 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8644 /* the last shift is signed */
8645 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8646 pic16_addSign(result, MSB32, sign);
8649 else{ /* 1 <= shCount <= 7 */
8651 shiftRLong(left, LSB, result, sign);
8653 shiftRLong(result, LSB, result, sign);
8656 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8657 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8658 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8663 /*-----------------------------------------------------------------*/
8664 /* genRightShiftLiteral - right shifting by known count */
8665 /*-----------------------------------------------------------------*/
8666 static void genRightShiftLiteral (operand *left,
8672 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8675 pic16_freeAsmop(right,NULL,ic,TRUE);
8677 pic16_aopOp(left,ic,FALSE);
8678 pic16_aopOp(result,ic,FALSE);
8680 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8683 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8687 lsize = pic16_getDataSize(left);
8688 res_size = pic16_getDataSize(result);
8689 /* test the LEFT size !!! */
8691 /* I suppose that the left size >= result size */
8694 movLeft2Result(left, lsize, result, res_size);
8697 else if(shCount >= (lsize * 8)){
8700 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8702 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8703 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8708 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8709 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8710 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8712 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8717 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8724 genrshOne (result,left,shCount,sign);
8728 genrshTwo (result,left,shCount,sign);
8732 genrshFour (result,left,shCount,sign);
8740 pic16_freeAsmop(left,NULL,ic,TRUE);
8741 pic16_freeAsmop(result,NULL,ic,TRUE);
8744 /*-----------------------------------------------------------------*/
8745 /* genSignedRightShift - right shift of signed number */
8746 /*-----------------------------------------------------------------*/
8747 static void genSignedRightShift (iCode *ic)
8749 operand *right, *left, *result;
8752 symbol *tlbl, *tlbl1 ;
8755 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8757 /* we do it the hard way put the shift count in b
8758 and loop thru preserving the sign */
8759 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8761 right = IC_RIGHT(ic);
8763 result = IC_RESULT(ic);
8765 pic16_aopOp(right,ic,FALSE);
8766 pic16_aopOp(left,ic,FALSE);
8767 pic16_aopOp(result,ic,FALSE);
8770 if ( AOP_TYPE(right) == AOP_LIT) {
8771 genRightShiftLiteral (left,right,result,ic,1);
8774 /* shift count is unknown then we have to form
8775 a loop get the loop count in B : Note: we take
8776 only the lower order byte since shifting
8777 more that 32 bits make no sense anyway, ( the
8778 largest size of an object can be only 32 bits ) */
8780 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8781 //pic16_emitcode("inc","b");
8782 //pic16_freeAsmop (right,NULL,ic,TRUE);
8783 //pic16_aopOp(left,ic,FALSE);
8784 //pic16_aopOp(result,ic,FALSE);
8786 /* now move the left to the result if they are not the
8788 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8789 AOP_SIZE(result) > 1) {
8791 size = AOP_SIZE(result);
8795 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8796 if (*l == '@' && IS_AOP_PREG(result)) {
8798 pic16_emitcode("mov","a,%s",l);
8799 pic16_aopPut(AOP(result),"a",offset);
8801 pic16_aopPut(AOP(result),l,offset);
8803 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8804 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8810 /* mov the highest order bit to OVR */
8811 tlbl = newiTempLabel(NULL);
8812 tlbl1= newiTempLabel(NULL);
8814 size = AOP_SIZE(result);
8817 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8819 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8821 /* offset should be 0, 1 or 3 */
8822 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8824 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8826 pic16_emitpcode(POC_MOVWF, pctemp);
8829 pic16_emitpLabel(tlbl->key);
8831 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
8832 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
8835 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
8838 pic16_emitpcode(POC_DECFSZ, pctemp);
8839 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8840 pic16_emitpLabel(tlbl1->key);
8842 pic16_popReleaseTempReg(pctemp);
8844 size = AOP_SIZE(result);
8846 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8847 pic16_emitcode("rlc","a");
8848 pic16_emitcode("mov","ov,c");
8849 /* if it is only one byte then */
8851 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8853 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8854 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8855 pic16_emitcode("mov","c,ov");
8856 pic16_emitcode("rrc","a");
8857 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8858 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8859 pic16_aopPut(AOP(result),"a",0);
8863 reAdjustPreg(AOP(result));
8864 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8865 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8866 pic16_emitcode("mov","c,ov");
8868 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8870 pic16_emitcode("rrc","a");
8871 pic16_aopPut(AOP(result),"a",offset--);
8873 reAdjustPreg(AOP(result));
8874 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8875 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8880 pic16_freeAsmop(left,NULL,ic,TRUE);
8881 pic16_freeAsmop(result,NULL,ic,TRUE);
8882 pic16_freeAsmop(right,NULL,ic,TRUE);
8885 /*-----------------------------------------------------------------*/
8886 /* genRightShift - generate code for right shifting */
8887 /*-----------------------------------------------------------------*/
8888 static void genRightShift (iCode *ic)
8890 operand *right, *left, *result;
8894 symbol *tlbl, *tlbl1 ;
8896 /* if signed then we do it the hard way preserve the
8897 sign bit moving it inwards */
8898 letype = getSpec(operandType(IC_LEFT(ic)));
8899 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8901 if (!SPEC_USIGN(letype)) {
8902 genSignedRightShift (ic);
8906 /* signed & unsigned types are treated the same : i.e. the
8907 signed is NOT propagated inwards : quoting from the
8908 ANSI - standard : "for E1 >> E2, is equivalent to division
8909 by 2**E2 if unsigned or if it has a non-negative value,
8910 otherwise the result is implementation defined ", MY definition
8911 is that the sign does not get propagated */
8913 right = IC_RIGHT(ic);
8915 result = IC_RESULT(ic);
8917 pic16_aopOp(right,ic,FALSE);
8919 /* if the shift count is known then do it
8920 as efficiently as possible */
8921 if (AOP_TYPE(right) == AOP_LIT) {
8922 genRightShiftLiteral (left,right,result,ic, 0);
8926 /* shift count is unknown then we have to form
8927 a loop get the loop count in B : Note: we take
8928 only the lower order byte since shifting
8929 more that 32 bits make no sense anyway, ( the
8930 largest size of an object can be only 32 bits ) */
8932 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8933 pic16_emitcode("inc","b");
8934 pic16_aopOp(left,ic,FALSE);
8935 pic16_aopOp(result,ic,FALSE);
8937 /* now move the left to the result if they are not the
8939 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8940 AOP_SIZE(result) > 1) {
8942 size = AOP_SIZE(result);
8945 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8946 if (*l == '@' && IS_AOP_PREG(result)) {
8948 pic16_emitcode("mov","a,%s",l);
8949 pic16_aopPut(AOP(result),"a",offset);
8951 pic16_aopPut(AOP(result),l,offset);
8956 tlbl = newiTempLabel(NULL);
8957 tlbl1= newiTempLabel(NULL);
8958 size = AOP_SIZE(result);
8961 /* if it is only one byte then */
8964 tlbl = newiTempLabel(NULL);
8965 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8966 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8967 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8970 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8971 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8972 pic16_emitpLabel(tlbl->key);
8973 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8974 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8976 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8981 reAdjustPreg(AOP(result));
8982 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8983 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8986 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8988 pic16_emitcode("rrc","a");
8989 pic16_aopPut(AOP(result),"a",offset--);
8991 reAdjustPreg(AOP(result));
8993 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8994 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8997 pic16_freeAsmop(left,NULL,ic,TRUE);
8998 pic16_freeAsmop (right,NULL,ic,TRUE);
8999 pic16_freeAsmop(result,NULL,ic,TRUE);
9002 /*-----------------------------------------------------------------*/
9003 /* genUnpackBits - generates code for unpacking bits */
9004 /*-----------------------------------------------------------------*/
9005 static void genUnpackBits (operand *result, char *rname, int ptype)
9012 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9013 etype = getSpec(operandType(result));
9015 /* read the first byte */
9022 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9025 pic16_emitcode("clr","a");
9026 pic16_emitcode("movc","a","@a+dptr");
9031 /* if we have bitdisplacement then it fits */
9032 /* into this byte completely or if length is */
9033 /* less than a byte */
9034 if ((shCnt = SPEC_BSTR(etype)) ||
9035 (SPEC_BLEN(etype) <= 8)) {
9037 /* shift right acc */
9040 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9041 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9043 /* VR -- normally I would use the following, but since we use the hack,
9044 * to avoid the masking from AccRsh, why not mask it right now? */
9047 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9050 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9056 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9057 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9060 /* bit field did not fit in a byte */
9061 rlen = SPEC_BLEN(etype) - 8;
9062 pic16_aopPut(AOP(result),"a",offset++);
9069 pic16_emitcode("inc","%s",rname);
9070 pic16_emitcode("mov","a,@%s",rname);
9074 pic16_emitcode("inc","%s",rname);
9075 pic16_emitcode("movx","a,@%s",rname);
9079 pic16_emitcode("inc","dptr");
9080 pic16_emitcode("movx","a,@dptr");
9084 pic16_emitcode("clr","a");
9085 pic16_emitcode("inc","dptr");
9086 pic16_emitcode("movc","a","@a+dptr");
9090 pic16_emitcode("inc","dptr");
9091 pic16_emitcode("lcall","__gptrget");
9096 /* if we are done */
9100 pic16_aopPut(AOP(result),"a",offset++);
9105 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9106 pic16_aopPut(AOP(result),"a",offset);
9113 static void genDataPointerGet(operand *left,
9117 int size, offset = 0, leoffset=0 ;
9119 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9120 pic16_aopOp(result, ic, FALSE);
9122 size = AOP_SIZE(result);
9123 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9127 /* The following tests may save a redudant movff instruction when
9128 * accessing unions */
9130 /* if they are the same */
9131 if (operandsEqu (left, result)) {
9132 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9138 /* if they are the same registers */
9139 if (pic16_sameRegs(AOP(left),AOP(result))) {
9140 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9146 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9147 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9148 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9155 if ( AOP_TYPE(left) == AOP_PCODE) {
9156 fprintf(stderr,"genDataPointerGet %s, %d\n",
9157 AOP(left)->aopu.pcop->name,
9158 (AOP(left)->aopu.pcop->type == PO_DIR)?
9159 PCOR(AOP(left)->aopu.pcop)->instance:
9160 PCOI(AOP(left)->aopu.pcop)->offset);
9164 if(AOP(left)->aopu.pcop->type == PO_DIR)
9165 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9167 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9170 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9172 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9173 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9174 mov2w(AOP(left), offset); // patch 8
9175 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9177 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9178 pic16_popGet(AOP(left), offset), //patch 8
9179 pic16_popGet(AOP(result), offset)));
9187 pic16_freeAsmop(result,NULL,ic,TRUE);
9190 void pic16_loadFSR0(operand *op)
9192 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9196 /*-----------------------------------------------------------------*/
9197 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
9198 /*-----------------------------------------------------------------*/
9199 static void genNearPointerGet (operand *left,
9204 //regs *preg = NULL ;
9205 sym_link *rtype, *retype;
9206 sym_link *ltype = operandType(left);
9208 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9209 rtype = operandType(result);
9210 retype= getSpec(rtype);
9212 pic16_aopOp(left,ic,FALSE);
9214 // pic16_DumpOp("(left)",left);
9215 // pic16_DumpOp("(result)",result);
9217 /* if left is rematerialisable and
9218 * result is not bit variable type and
9219 * the left is pointer to data space i.e
9220 * lower 128 bytes of space */
9221 if (AOP_TYPE(left) == AOP_PCODE
9222 && !IS_BITFIELD(retype)
9223 && DCL_TYPE(ltype) == POINTER) {
9225 genDataPointerGet (left,result,ic);
9226 pic16_freeAsmop(left, NULL, ic, TRUE);
9230 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9232 /* if the value is already in a pointer register
9233 * then don't need anything more */
9234 if (!AOP_INPREG(AOP(left))) {
9235 /* otherwise get a free pointer register */
9236 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9238 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9239 if( (AOP_TYPE(left) == AOP_PCODE)
9240 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9241 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9243 pic16_loadFSR0( left ); // patch 10
9245 // set up FSR0 with address from left
9246 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9247 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9251 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9253 pic16_aopOp (result,ic,FALSE);
9255 /* if bitfield then unpack the bits */
9256 if (IS_BITFIELD(retype))
9257 genUnpackBits (result, NULL, POINTER);
9259 /* we have can just get the values */
9260 int size = AOP_SIZE(result);
9263 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9266 /* fsr0 is loaded already -- VR */
9267 // pic16_loadFSR0( left );
9269 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9270 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9274 pic16_emitpcode(POC_MOVFF,
9275 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9276 pic16_popGet(AOP(result), offset++)));
9278 pic16_emitpcode(POC_MOVFF,
9279 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9280 pic16_popGet(AOP(result), offset++)));
9284 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9285 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9287 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9291 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9293 pic16_emitcode("mov","a,@%s",rname);
9294 pic16_aopPut(AOP(result),"a",offset);
9296 sprintf(buffer,"@%s",rname);
9297 pic16_aopPut(AOP(result),buffer,offset);
9301 pic16_emitcode("inc","%s",rname);
9306 /* now some housekeeping stuff */
9308 /* we had to allocate for this iCode */
9309 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9310 pic16_freeAsmop(NULL,aop,ic,TRUE);
9312 /* we did not allocate which means left
9313 already in a pointer register, then
9314 if size > 0 && this could be used again
9315 we have to point it back to where it
9317 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9318 if (AOP_SIZE(result) > 1 &&
9319 !OP_SYMBOL(left)->remat &&
9320 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9322 // int size = AOP_SIZE(result) - 1;
9324 // pic16_emitcode("dec","%s",rname);
9329 pic16_freeAsmop(left,NULL,ic,TRUE);
9330 pic16_freeAsmop(result,NULL,ic,TRUE);
9334 /*-----------------------------------------------------------------*/
9335 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
9336 /*-----------------------------------------------------------------*/
9337 static void genPagedPointerGet (operand *left,
9344 sym_link *rtype, *retype;
9346 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9348 rtype = operandType(result);
9349 retype= getSpec(rtype);
9351 pic16_aopOp(left,ic,FALSE);
9353 /* if the value is already in a pointer register
9354 then don't need anything more */
9355 if (!AOP_INPREG(AOP(left))) {
9356 /* otherwise get a free pointer register */
9358 preg = getFreePtr(ic,&aop,FALSE);
9359 pic16_emitcode("mov","%s,%s",
9361 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9362 rname = preg->name ;
9364 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9366 pic16_freeAsmop(left,NULL,ic,TRUE);
9367 pic16_aopOp (result,ic,FALSE);
9369 /* if bitfield then unpack the bits */
9370 if (IS_BITFIELD(retype))
9371 genUnpackBits (result,rname,PPOINTER);
9373 /* we have can just get the values */
9374 int size = AOP_SIZE(result);
9379 pic16_emitcode("movx","a,@%s",rname);
9380 pic16_aopPut(AOP(result),"a",offset);
9385 pic16_emitcode("inc","%s",rname);
9389 /* now some housekeeping stuff */
9391 /* we had to allocate for this iCode */
9392 pic16_freeAsmop(NULL,aop,ic,TRUE);
9394 /* we did not allocate which means left
9395 already in a pointer register, then
9396 if size > 0 && this could be used again
9397 we have to point it back to where it
9399 if (AOP_SIZE(result) > 1 &&
9400 !OP_SYMBOL(left)->remat &&
9401 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9403 int size = AOP_SIZE(result) - 1;
9405 pic16_emitcode("dec","%s",rname);
9410 pic16_freeAsmop(result,NULL,ic,TRUE);
9415 /*-----------------------------------------------------------------*/
9416 /* genFarPointerGet - gget value from far space */
9417 /*-----------------------------------------------------------------*/
9418 static void genFarPointerGet (operand *left,
9419 operand *result, iCode *ic)
9422 sym_link *retype = getSpec(operandType(result));
9424 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9426 pic16_aopOp(left,ic,FALSE);
9428 /* if the operand is already in dptr
9429 then we do nothing else we move the value to dptr */
9430 if (AOP_TYPE(left) != AOP_STR) {
9431 /* if this is remateriazable */
9432 if (AOP_TYPE(left) == AOP_IMMD)
9433 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9434 else { /* we need to get it byte by byte */
9435 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9436 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9437 if (options.model == MODEL_FLAT24)
9439 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9443 /* so dptr know contains the address */
9444 pic16_freeAsmop(left,NULL,ic,TRUE);
9445 pic16_aopOp(result,ic,FALSE);
9447 /* if bit then unpack */
9448 if (IS_BITFIELD(retype))
9449 genUnpackBits(result,"dptr",FPOINTER);
9451 size = AOP_SIZE(result);
9455 pic16_emitcode("movx","a,@dptr");
9456 pic16_aopPut(AOP(result),"a",offset++);
9458 pic16_emitcode("inc","dptr");
9462 pic16_freeAsmop(result,NULL,ic,TRUE);
9465 /*-----------------------------------------------------------------*/
9466 /* genCodePointerGet - get value from code space */
9467 /*-----------------------------------------------------------------*/
9468 static void genCodePointerGet (operand *left,
9469 operand *result, iCode *ic)
9472 sym_link *retype = getSpec(operandType(result));
9474 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9476 pic16_aopOp(left,ic,FALSE);
9478 /* if the operand is already in dptr
9479 then we do nothing else we move the value to dptr */
9480 if (AOP_TYPE(left) != AOP_STR) {
9481 /* if this is remateriazable */
9482 if (AOP_TYPE(left) == AOP_IMMD)
9483 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9484 else { /* we need to get it byte by byte */
9485 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9486 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9487 if (options.model == MODEL_FLAT24)
9489 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9493 /* so dptr know contains the address */
9494 pic16_freeAsmop(left,NULL,ic,TRUE);
9495 pic16_aopOp(result,ic,FALSE);
9497 /* if bit then unpack */
9498 if (IS_BITFIELD(retype))
9499 genUnpackBits(result,"dptr",CPOINTER);
9501 size = AOP_SIZE(result);
9505 pic16_emitcode("clr","a");
9506 pic16_emitcode("movc","a,@a+dptr");
9507 pic16_aopPut(AOP(result),"a",offset++);
9509 pic16_emitcode("inc","dptr");
9513 pic16_freeAsmop(result,NULL,ic,TRUE);
9516 /*-----------------------------------------------------------------*/
9517 /* genGenPointerGet - gget value from generic pointer space */
9518 /*-----------------------------------------------------------------*/
9519 static void genGenPointerGet (operand *left,
9520 operand *result, iCode *ic)
9522 int size, offset, lit;
9523 sym_link *retype = getSpec(operandType(result));
9525 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9526 pic16_aopOp(left,ic,FALSE);
9527 pic16_aopOp(result,ic,FALSE);
9528 size = AOP_SIZE(result);
9530 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9532 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9534 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9535 // load FSR0 from immediate
9536 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9538 // pic16_loadFSR0( left );
9543 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9545 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9552 else { /* we need to get it byte by byte */
9553 // set up FSR0 with address from left
9554 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9555 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9561 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9563 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9570 /* if bit then unpack */
9571 if (IS_BITFIELD(retype))
9572 genUnpackBits(result,"BAD",GPOINTER);
9575 pic16_freeAsmop(left,NULL,ic,TRUE);
9576 pic16_freeAsmop(result,NULL,ic,TRUE);
9580 /*-----------------------------------------------------------------*/
9581 /* genConstPointerGet - get value from const generic pointer space */
9582 /*-----------------------------------------------------------------*/
9583 static void genConstPointerGet (operand *left,
9584 operand *result, iCode *ic)
9586 //sym_link *retype = getSpec(operandType(result));
9587 // symbol *albl = newiTempLabel(NULL); // patch 15
9588 // symbol *blbl = newiTempLabel(NULL); //
9589 // PIC_OPCODE poc; // patch 15
9593 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9594 pic16_aopOp(left,ic,FALSE);
9595 pic16_aopOp(result,ic,TRUE);
9596 size = AOP_SIZE(result);
9598 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9600 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9602 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9603 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9604 pic16_emitpLabel(albl->key);
9606 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9608 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9609 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9610 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9611 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9612 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9614 pic16_emitpLabel(blbl->key);
9616 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9620 // set up table pointer
9621 if( (AOP_TYPE(left) == AOP_PCODE)
9622 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9623 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
9625 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9626 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9627 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9628 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9629 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9630 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9634 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9635 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9636 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9642 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9643 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9647 pic16_freeAsmop(left,NULL,ic,TRUE);
9648 pic16_freeAsmop(result,NULL,ic,TRUE);
9653 /*-----------------------------------------------------------------*/
9654 /* genPointerGet - generate code for pointer get */
9655 /*-----------------------------------------------------------------*/
9656 static void genPointerGet (iCode *ic)
9658 operand *left, *result ;
9659 sym_link *type, *etype;
9662 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9665 result = IC_RESULT(ic) ;
9667 /* depending on the type of pointer we need to
9668 move it to the correct pointer register */
9669 type = operandType(left);
9670 etype = getSpec(type);
9673 if (IS_PTR_CONST(type))
9675 if (IS_CODEPTR(type))
9677 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9679 /* if left is of type of pointer then it is simple */
9680 if (IS_PTR(type) && !IS_FUNC(type->next))
9681 p_type = DCL_TYPE(type);
9683 /* we have to go by the storage class */
9684 p_type = PTR_TYPE(SPEC_OCLS(etype));
9686 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9688 if (SPEC_OCLS(etype)->codesp ) {
9689 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9690 //p_type = CPOINTER ;
9693 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9694 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9695 /*p_type = FPOINTER ;*/
9697 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9698 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9699 /* p_type = PPOINTER; */
9701 if (SPEC_OCLS(etype) == idata )
9702 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9703 /* p_type = IPOINTER; */
9705 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9706 /* p_type = POINTER ; */
9709 /* now that we have the pointer type we assign
9710 the pointer values */
9715 genNearPointerGet (left,result,ic);
9719 genPagedPointerGet(left,result,ic);
9723 genFarPointerGet (left,result,ic);
9727 genConstPointerGet (left,result,ic);
9728 //pic16_emitcodePointerGet (left,result,ic);
9733 if (IS_PTR_CONST(type))
9734 genConstPointerGet (left,result,ic);
9737 genGenPointerGet (left,result,ic);
9741 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9742 "genPointerGet: illegal pointer type");
9748 /*-----------------------------------------------------------------*/
9749 /* genPackBits - generates code for packed bit storage */
9750 /*-----------------------------------------------------------------*/
9751 static void genPackBits (sym_link *etype ,
9753 char *rname, int p_type)
9761 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9762 blen = SPEC_BLEN(etype);
9763 bstr = SPEC_BSTR(etype);
9765 if(AOP_TYPE(right) == AOP_LIT) {
9766 if((blen == 1) && (bstr < 8)) {
9768 /* it is a single bit, so use the appropriate bit instructions */
9770 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9772 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9773 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9775 pic16_emitpcode(POC_BSF,
9776 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9778 pic16_emitpcode(POC_BCF,
9779 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9785 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9788 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9790 /* if the bit lenth is less than or */
9791 /* it exactly fits a byte then */
9792 if((shCnt=SPEC_BSTR(etype))
9793 || SPEC_BLEN(etype) <= 8 ) {
9795 /* shift left acc */
9798 /* using PRODL as a temporary register here */
9799 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9805 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9806 // pic16_emitcode ("mov","b,a");
9807 // pic16_emitcode("mov","a,@%s",rname);
9811 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9812 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9813 (unsigned char)(0xff >> (8-bstr))) ));
9814 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9815 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9822 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9823 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9828 if ( SPEC_BLEN(etype) <= 8 )
9831 pic16_emitcode("inc","%s",rname);
9832 rLen = SPEC_BLEN(etype) ;
9836 /* now generate for lengths greater than one byte */
9839 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9849 pic16_emitcode("mov","@%s,a",rname);
9851 pic16_emitcode("mov","@%s,%s",rname,l);
9856 pic16_emitcode("movx","@dptr,a");
9861 DEBUGpic16_emitcode(";lcall","__gptrput");
9864 pic16_emitcode ("inc","%s",rname);
9869 /* last last was not complete */
9871 /* save the byte & read byte */
9874 pic16_emitcode ("mov","b,a");
9875 pic16_emitcode("mov","a,@%s",rname);
9879 pic16_emitcode ("mov","b,a");
9880 pic16_emitcode("movx","a,@dptr");
9884 pic16_emitcode ("push","b");
9885 pic16_emitcode ("push","acc");
9886 pic16_emitcode ("lcall","__gptrget");
9887 pic16_emitcode ("pop","b");
9891 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9892 pic16_emitcode ("orl","a,b");
9895 if (p_type == GPOINTER)
9896 pic16_emitcode("pop","b");
9901 pic16_emitcode("mov","@%s,a",rname);
9905 pic16_emitcode("movx","@dptr,a");
9909 DEBUGpic16_emitcode(";lcall","__gptrput");
9913 /*-----------------------------------------------------------------*/
9914 /* genDataPointerSet - remat pointer to data space */
9915 /*-----------------------------------------------------------------*/
9916 static void genDataPointerSet(operand *right,
9920 int size, offset = 0, resoffset=0 ;
9922 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9923 pic16_aopOp(right,ic,FALSE);
9925 size = AOP_SIZE(right);
9927 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9930 if ( AOP_TYPE(result) == AOP_PCODE) {
9931 fprintf(stderr,"genDataPointerSet %s, %d\n",
9932 AOP(result)->aopu.pcop->name,
9933 (AOP(result)->aopu.pcop->type == PO_DIR)?
9934 PCOR(AOP(result)->aopu.pcop)->instance:
9935 PCOI(AOP(result)->aopu.pcop)->offset);
9939 if(AOP(result)->aopu.pcop->type == PO_DIR)
9940 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9943 if (AOP_TYPE(right) == AOP_LIT) {
9944 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9946 lit = lit >> (8*offset);
9948 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9949 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9951 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9954 mov2w(AOP(right), offset);
9955 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9961 pic16_freeAsmop(right,NULL,ic,TRUE);
9966 /*-----------------------------------------------------------------*/
9967 /* genNearPointerSet - pic16_emitcode for near pointer put */
9968 /*-----------------------------------------------------------------*/
9969 static void genNearPointerSet (operand *right,
9976 sym_link *ptype = operandType(result);
9979 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9980 retype= getSpec(operandType(right));
9981 resetype = getSpec(operandType(result));
9983 pic16_aopOp(result,ic,FALSE);
9985 /* if the result is rematerializable &
9986 * in data space & not a bit variable */
9988 /* and result is not a bit variable */
9989 if (AOP_TYPE(result) == AOP_PCODE
9990 // && AOP_TYPE(result) == AOP_IMMD
9991 && DCL_TYPE(ptype) == POINTER
9992 && !IS_BITFIELD(retype)
9993 && !IS_BITFIELD(resetype)) {
9995 genDataPointerSet (right,result,ic);
9996 pic16_freeAsmop(result,NULL,ic,TRUE);
10000 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10001 pic16_aopOp(right,ic,FALSE);
10002 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10004 /* if the value is already in a pointer register
10005 * then don't need anything more */
10006 if (!AOP_INPREG(AOP(result))) {
10007 /* otherwise get a free pointer register */
10008 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10010 if( (AOP_TYPE(result) == AOP_PCODE)
10011 && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10012 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10014 pic16_loadFSR0( result ); // patch 10
10016 // set up FSR0 with address of result
10017 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10018 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10023 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10025 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10027 /* if bitfield then unpack the bits */
10028 if (IS_BITFIELD(resetype)) {
10029 genPackBits (resetype, right, NULL, POINTER);
10031 /* we have can just get the values */
10032 int size = AOP_SIZE(right);
10035 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10037 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10040 //pic16_emitcode("mov","@%s,a",rname);
10041 pic16_emitcode("movf","indf0,w ;1");
10044 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
10045 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
10047 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
10049 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
10051 } else { // no literal //
10053 pic16_emitpcode(POC_MOVFF, //
10054 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10055 pic16_popCopyReg(&pic16_pc_postinc0))); //
10057 pic16_emitpcode(POC_MOVFF, //
10058 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10059 pic16_popCopyReg(&pic16_pc_indf0))); //
10067 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10068 /* now some housekeeping stuff */
10070 /* we had to allocate for this iCode */
10071 pic16_freeAsmop(NULL,aop,ic,TRUE);
10073 /* we did not allocate which means left
10074 * already in a pointer register, then
10075 * if size > 0 && this could be used again
10076 * we have to point it back to where it
10078 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10079 if (AOP_SIZE(right) > 1
10080 && !OP_SYMBOL(result)->remat
10081 && ( OP_SYMBOL(result)->liveTo > ic->seq
10084 int size = AOP_SIZE(right) - 1;
10087 pic16_emitcode("decf","fsr0,f");
10088 //pic16_emitcode("dec","%s",rname);
10092 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10095 pic16_freeAsmop(right,NULL,ic,TRUE);
10096 pic16_freeAsmop(result,NULL,ic,TRUE);
10099 /*-----------------------------------------------------------------*/
10100 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
10101 /*-----------------------------------------------------------------*/
10102 static void genPagedPointerSet (operand *right,
10107 regs *preg = NULL ;
10111 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10113 retype= getSpec(operandType(right));
10115 pic16_aopOp(result,ic,FALSE);
10117 /* if the value is already in a pointer register
10118 then don't need anything more */
10119 if (!AOP_INPREG(AOP(result))) {
10120 /* otherwise get a free pointer register */
10122 preg = getFreePtr(ic,&aop,FALSE);
10123 pic16_emitcode("mov","%s,%s",
10125 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10126 rname = preg->name ;
10128 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10130 pic16_freeAsmop(result,NULL,ic,TRUE);
10131 pic16_aopOp (right,ic,FALSE);
10133 /* if bitfield then unpack the bits */
10134 if (IS_BITFIELD(retype))
10135 genPackBits (retype,right,rname,PPOINTER);
10137 /* we have can just get the values */
10138 int size = AOP_SIZE(right);
10142 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10145 pic16_emitcode("movx","@%s,a",rname);
10148 pic16_emitcode("inc","%s",rname);
10154 /* now some housekeeping stuff */
10156 /* we had to allocate for this iCode */
10157 pic16_freeAsmop(NULL,aop,ic,TRUE);
10159 /* we did not allocate which means left
10160 already in a pointer register, then
10161 if size > 0 && this could be used again
10162 we have to point it back to where it
10164 if (AOP_SIZE(right) > 1 &&
10165 !OP_SYMBOL(result)->remat &&
10166 ( OP_SYMBOL(result)->liveTo > ic->seq ||
10168 int size = AOP_SIZE(right) - 1;
10170 pic16_emitcode("dec","%s",rname);
10175 pic16_freeAsmop(right,NULL,ic,TRUE);
10180 /*-----------------------------------------------------------------*/
10181 /* genFarPointerSet - set value from far space */
10182 /*-----------------------------------------------------------------*/
10183 static void genFarPointerSet (operand *right,
10184 operand *result, iCode *ic)
10187 sym_link *retype = getSpec(operandType(right));
10189 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10190 pic16_aopOp(result,ic,FALSE);
10192 /* if the operand is already in dptr
10193 then we do nothing else we move the value to dptr */
10194 if (AOP_TYPE(result) != AOP_STR) {
10195 /* if this is remateriazable */
10196 if (AOP_TYPE(result) == AOP_IMMD)
10197 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10198 else { /* we need to get it byte by byte */
10199 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10200 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10201 if (options.model == MODEL_FLAT24)
10203 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10207 /* so dptr know contains the address */
10208 pic16_freeAsmop(result,NULL,ic,TRUE);
10209 pic16_aopOp(right,ic,FALSE);
10211 /* if bit then unpack */
10212 if (IS_BITFIELD(retype))
10213 genPackBits(retype,right,"dptr",FPOINTER);
10215 size = AOP_SIZE(right);
10219 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10221 pic16_emitcode("movx","@dptr,a");
10223 pic16_emitcode("inc","dptr");
10227 pic16_freeAsmop(right,NULL,ic,TRUE);
10230 /*-----------------------------------------------------------------*/
10231 /* genGenPointerSet - set value from generic pointer space */
10232 /*-----------------------------------------------------------------*/
10233 static void genGenPointerSet (operand *right,
10234 operand *result, iCode *ic)
10236 int i, size, offset, lit;
10237 sym_link *retype = getSpec(operandType(right));
10239 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10241 pic16_aopOp(result,ic,FALSE);
10242 pic16_aopOp(right,ic,FALSE);
10243 size = AOP_SIZE(right);
10246 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10248 /* if the operand is already in dptr
10249 then we do nothing else we move the value to dptr */
10250 if (AOP_TYPE(result) != AOP_STR) {
10251 /* if this is remateriazable */
10252 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10253 // WARNING: anythig until "else" is untested!
10254 if (AOP_TYPE(result) == AOP_IMMD) {
10255 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10256 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10257 // load FSR0 from immediate
10258 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10262 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10264 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10270 else { /* we need to get it byte by byte */
10271 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10272 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10274 // set up FSR0 with address of result
10275 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10276 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10278 /* hack hack! see if this the FSR. If so don't load W */
10279 if(AOP_TYPE(right) != AOP_ACC) {
10281 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10283 if(AOP_TYPE(right) == AOP_LIT)
10286 // note: pic16_popGet handles sign extension
10287 for(i=0;i<size;i++) {
10288 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10290 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10292 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10297 for(i=0;i<size;i++) {
10299 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10300 pic16_popCopyReg(&pic16_pc_postinc0)));
10302 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10303 pic16_popCopyReg(&pic16_pc_indf0)));
10309 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10310 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10312 } // if (AOP_TYPE(result) != AOP_IMMD)
10314 } // if (AOP_TYPE(result) != AOP_STR)
10315 /* so dptr know contains the address */
10318 /* if bit then unpack */
10319 if (IS_BITFIELD(retype))
10320 genPackBits(retype,right,"dptr",GPOINTER);
10322 size = AOP_SIZE(right);
10325 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
10327 // set up FSR0 with address of result
10328 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10329 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10332 if (AOP_TYPE(right) == AOP_LIT) {
10333 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10335 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10337 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10339 } else { // no literal
10341 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10343 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10351 pic16_freeAsmop(right,NULL,ic,TRUE);
10352 pic16_freeAsmop(result,NULL,ic,TRUE);
10355 /*-----------------------------------------------------------------*/
10356 /* genPointerSet - stores the value into a pointer location */
10357 /*-----------------------------------------------------------------*/
10358 static void genPointerSet (iCode *ic)
10360 operand *right, *result ;
10361 sym_link *type, *etype;
10364 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10366 right = IC_RIGHT(ic);
10367 result = IC_RESULT(ic) ;
10369 /* depending on the type of pointer we need to
10370 move it to the correct pointer register */
10371 type = operandType(result);
10372 etype = getSpec(type);
10373 /* if left is of type of pointer then it is simple */
10374 if (IS_PTR(type) && !IS_FUNC(type->next)) {
10375 p_type = DCL_TYPE(type);
10378 /* we have to go by the storage class */
10379 p_type = PTR_TYPE(SPEC_OCLS(etype));
10381 /* if (SPEC_OCLS(etype)->codesp ) { */
10382 /* p_type = CPOINTER ; */
10385 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10386 /* p_type = FPOINTER ; */
10388 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10389 /* p_type = PPOINTER ; */
10391 /* if (SPEC_OCLS(etype) == idata ) */
10392 /* p_type = IPOINTER ; */
10394 /* p_type = POINTER ; */
10397 /* now that we have the pointer type we assign
10398 the pointer values */
10403 genNearPointerSet (right,result,ic);
10407 genPagedPointerSet (right,result,ic);
10411 genFarPointerSet (right,result,ic);
10415 genGenPointerSet (right,result,ic);
10419 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10420 "genPointerSet: illegal pointer type");
10424 /*-----------------------------------------------------------------*/
10425 /* genIfx - generate code for Ifx statement */
10426 /*-----------------------------------------------------------------*/
10427 static void genIfx (iCode *ic, iCode *popIc)
10429 operand *cond = IC_COND(ic);
10432 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10434 pic16_aopOp(cond,ic,FALSE);
10436 /* get the value into acc */
10437 if (AOP_TYPE(cond) != AOP_CRY)
10438 pic16_toBoolean(cond);
10441 /* the result is now in the accumulator */
10442 pic16_freeAsmop(cond,NULL,ic,TRUE);
10444 /* if there was something to be popped then do it */
10448 /* if the condition is a bit variable */
10449 if (isbit && IS_ITEMP(cond) &&
10451 genIfxJump(ic,SPIL_LOC(cond)->rname);
10452 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10455 if (isbit && !IS_ITEMP(cond))
10456 genIfxJump(ic,OP_SYMBOL(cond)->rname);
10458 genIfxJump(ic,"a");
10464 /*-----------------------------------------------------------------*/
10465 /* genAddrOf - generates code for address of */
10466 /*-----------------------------------------------------------------*/
10467 static void genAddrOf (iCode *ic)
10469 operand *result, *left;
10471 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
10472 pCodeOp *pcop0, *pcop1, *pcop2;
10474 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10476 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10477 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10479 sym = OP_SYMBOL( left );
10481 size = AOP_SIZE(IC_RESULT(ic));
10483 // if(pic16_debug_verbose) {
10484 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10485 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10488 /* Assume that what we want the address of is in data space
10489 * since there is no stack on the PIC, yet! -- VR */
10491 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10494 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10497 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10501 pic16_emitpcode(POC_MOVLW, pcop0);
10502 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10503 pic16_emitpcode(POC_MOVLW, pcop1);
10504 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10505 pic16_emitpcode(POC_MOVLW, pcop2);
10506 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10509 pic16_emitpcode(POC_MOVLW, pcop0);
10510 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10511 pic16_emitpcode(POC_MOVLW, pcop1);
10512 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10514 pic16_emitpcode(POC_MOVLW, pcop0);
10515 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10518 pic16_freeAsmop(result,NULL,ic,TRUE);
10519 pic16_freeAsmop(left, NULL, ic, FALSE);
10524 /*-----------------------------------------------------------------*/
10525 /* genFarFarAssign - assignment when both are in far space */
10526 /*-----------------------------------------------------------------*/
10527 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10529 int size = AOP_SIZE(right);
10532 /* first push the right side on to the stack */
10534 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10536 pic16_emitcode ("push","acc");
10539 pic16_freeAsmop(right,NULL,ic,FALSE);
10540 /* now assign DPTR to result */
10541 pic16_aopOp(result,ic,FALSE);
10542 size = AOP_SIZE(result);
10544 pic16_emitcode ("pop","acc");
10545 pic16_aopPut(AOP(result),"a",--offset);
10547 pic16_freeAsmop(result,NULL,ic,FALSE);
10552 /*-----------------------------------------------------------------*/
10553 /* genAssign - generate code for assignment */
10554 /*-----------------------------------------------------------------*/
10555 static void genAssign (iCode *ic)
10557 operand *result, *right;
10558 int size, offset,know_W;
10559 unsigned long lit = 0L;
10561 result = IC_RESULT(ic);
10562 right = IC_RIGHT(ic) ;
10564 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10566 /* if they are the same */
10567 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10570 pic16_aopOp(right,ic,FALSE);
10571 pic16_aopOp(result,ic,TRUE);
10573 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10575 /* if they are the same registers */
10576 if (pic16_sameRegs(AOP(right),AOP(result)))
10579 /* if the result is a bit */
10580 if (AOP_TYPE(result) == AOP_CRY) {
10581 /* if the right size is a literal then
10582 we know what the value is */
10583 if (AOP_TYPE(right) == AOP_LIT) {
10585 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10586 pic16_popGet(AOP(result),0));
10588 if (((int) operandLitValue(right)))
10589 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10590 AOP(result)->aopu.aop_dir,
10591 AOP(result)->aopu.aop_dir);
10593 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10594 AOP(result)->aopu.aop_dir,
10595 AOP(result)->aopu.aop_dir);
10599 /* the right is also a bit variable */
10600 if (AOP_TYPE(right) == AOP_CRY) {
10601 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10602 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10603 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10605 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10606 AOP(result)->aopu.aop_dir,
10607 AOP(result)->aopu.aop_dir);
10608 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10609 AOP(right)->aopu.aop_dir,
10610 AOP(right)->aopu.aop_dir);
10611 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10612 AOP(result)->aopu.aop_dir,
10613 AOP(result)->aopu.aop_dir);
10617 /* we need to or */
10618 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10619 pic16_toBoolean(right);
10621 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10622 //pic16_aopPut(AOP(result),"a",0);
10626 /* bit variables done */
10628 size = AOP_SIZE(result);
10631 if(AOP_TYPE(right) == AOP_LIT) {
10632 if(!IS_FLOAT(operandType( right )))
10633 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10636 unsigned long lit_int;
10640 /* take care if literal is a float */
10641 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10642 lit = info.lit_int;
10646 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10647 // sizeof(unsigned long int), sizeof(float));
10649 if(AOP_TYPE(right) != AOP_LIT
10650 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10651 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10653 // set up table pointer
10654 if( (AOP_TYPE(right) == AOP_PCODE)
10655 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10656 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10658 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10659 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10660 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10661 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10662 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10663 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10665 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10666 pic16_popCopyReg(&pic16_pc_tblptrl)));
10667 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10668 pic16_popCopyReg(&pic16_pc_tblptrh)));
10669 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10670 pic16_popCopyReg(&pic16_pc_tblptru)));
10673 size = min(AOP_SIZE(right), AOP_SIZE(result));
10675 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10676 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10677 pic16_popGet(AOP(result),offset)));
10681 if(AOP_SIZE(result) > AOP_SIZE(right)) {
10682 size = AOP_SIZE(result) - AOP_SIZE(right);
10684 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10693 /* VR - What is this?! */
10694 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10695 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10696 if(aopIdx(AOP(result),0) == 4) {
10697 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10699 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10700 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10704 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10709 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10710 if(AOP_TYPE(right) == AOP_LIT) {
10712 if(know_W != (lit&0xff))
10713 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10715 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10717 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10721 } else if (AOP_TYPE(right) == AOP_CRY) {
10722 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10724 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10725 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10727 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10728 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10729 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10731 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10734 /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10735 normally should work, but mind that the W register live range
10736 is not checked, so if the code generator assumes that the W
10737 is already loaded after such a pair, wrong code will be generated.
10739 Checking the live range is the next step.
10740 This is experimental code yet and has not been fully tested yet.
10741 USE WITH CARE. Revert to old code by setting 0 to the condition above.
10742 Vangelis Rokas 030603 (vrokas@otenet.gr) */
10744 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10746 /* This is the old code, which is assumed(?!) that works fine(!?) */
10748 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10749 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10758 pic16_freeAsmop (right,NULL,ic,FALSE);
10759 pic16_freeAsmop (result,NULL,ic,TRUE);
10762 /*-----------------------------------------------------------------*/
10763 /* genJumpTab - generates code for jump table */
10764 /*-----------------------------------------------------------------*/
10765 static void genJumpTab (iCode *ic)
10770 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10772 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10773 /* get the condition into accumulator */
10774 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10776 /* multiply by three */
10777 pic16_emitcode("add","a,acc");
10778 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10780 jtab = newiTempLabel(NULL);
10781 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10782 pic16_emitcode("jmp","@a+dptr");
10783 pic16_emitcode("","%05d_DS_:",jtab->key+100);
10785 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10786 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10788 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10789 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10790 pic16_emitpLabel(jtab->key);
10792 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10794 /* now generate the jump labels */
10795 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10796 jtab = setNextItem(IC_JTLABELS(ic))) {
10797 pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10798 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10804 /*-----------------------------------------------------------------*/
10805 /* genMixedOperation - gen code for operators between mixed types */
10806 /*-----------------------------------------------------------------*/
10808 TSD - Written for the PIC port - but this unfortunately is buggy.
10809 This routine is good in that it is able to efficiently promote
10810 types to different (larger) sizes. Unfortunately, the temporary
10811 variables that are optimized out by this routine are sometimes
10812 used in other places. So until I know how to really parse the
10813 iCode tree, I'm going to not be using this routine :(.
10815 static int genMixedOperation (iCode *ic)
10818 operand *result = IC_RESULT(ic);
10819 sym_link *ctype = operandType(IC_LEFT(ic));
10820 operand *right = IC_RIGHT(ic);
10826 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10828 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10834 nextright = IC_RIGHT(nextic);
10835 nextleft = IC_LEFT(nextic);
10836 nextresult = IC_RESULT(nextic);
10838 pic16_aopOp(right,ic,FALSE);
10839 pic16_aopOp(result,ic,FALSE);
10840 pic16_aopOp(nextright, nextic, FALSE);
10841 pic16_aopOp(nextleft, nextic, FALSE);
10842 pic16_aopOp(nextresult, nextic, FALSE);
10844 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10846 operand *t = right;
10850 pic16_emitcode(";remove right +","");
10852 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10854 operand *t = right;
10858 pic16_emitcode(";remove left +","");
10862 big = AOP_SIZE(nextleft);
10863 small = AOP_SIZE(nextright);
10865 switch(nextic->op) {
10868 pic16_emitcode(";optimize a +","");
10869 /* if unsigned or not an integral type */
10870 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10871 pic16_emitcode(";add a bit to something","");
10874 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10876 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10877 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10878 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10880 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10888 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10889 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10890 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10893 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10895 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10896 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10897 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10898 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10899 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10902 pic16_emitcode("rlf","known_zero,w");
10909 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10910 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10911 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10913 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10923 pic16_freeAsmop(right,NULL,ic,TRUE);
10924 pic16_freeAsmop(result,NULL,ic,TRUE);
10925 pic16_freeAsmop(nextright,NULL,ic,TRUE);
10926 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10928 nextic->generated = 1;
10935 /*-----------------------------------------------------------------*/
10936 /* genCast - gen code for casting */
10937 /*-----------------------------------------------------------------*/
10938 static void genCast (iCode *ic)
10940 operand *result = IC_RESULT(ic);
10941 sym_link *ctype = operandType(IC_LEFT(ic));
10942 sym_link *rtype = operandType(IC_RIGHT(ic));
10943 operand *right = IC_RIGHT(ic);
10946 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10947 /* if they are equivalent then do nothing */
10948 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10951 pic16_aopOp(right,ic,FALSE) ;
10952 pic16_aopOp(result,ic,FALSE);
10954 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10956 /* if the result is a bit */
10957 if (AOP_TYPE(result) == AOP_CRY) {
10959 /* if the right size is a literal then
10960 * we know what the value is */
10961 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10963 if (AOP_TYPE(right) == AOP_LIT) {
10964 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10965 pic16_popGet(AOP(result),0));
10967 if (((int) operandLitValue(right)))
10968 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10969 AOP(result)->aopu.aop_dir,
10970 AOP(result)->aopu.aop_dir);
10972 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10973 AOP(result)->aopu.aop_dir,
10974 AOP(result)->aopu.aop_dir);
10978 /* the right is also a bit variable */
10979 if (AOP_TYPE(right) == AOP_CRY) {
10981 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10983 pic16_emitcode("clrc","");
10984 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10985 AOP(right)->aopu.aop_dir,
10986 AOP(right)->aopu.aop_dir);
10987 pic16_aopPut(AOP(result),"c",0);
10991 /* we need to or */
10992 if (AOP_TYPE(right) == AOP_REG) {
10993 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10994 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10995 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10997 pic16_toBoolean(right);
10998 pic16_aopPut(AOP(result),"a",0);
11002 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11005 size = AOP_SIZE(result);
11007 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11009 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
11010 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11011 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
11014 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11019 /* if they are the same size : or less */
11020 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11022 /* if they are in the same place */
11023 if (pic16_sameRegs(AOP(right),AOP(result)))
11026 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11028 if (IS_PTR_CONST(rtype))
11030 if (IS_CODEPTR(rtype))
11032 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11035 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11037 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11039 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11042 if(AOP_TYPE(right) == AOP_IMMD) {
11043 pCodeOp *pcop0, *pcop1, *pcop2;
11044 symbol *sym = OP_SYMBOL( right );
11046 size = AOP_SIZE(result);
11048 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11050 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11052 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11055 pic16_emitpcode(POC_MOVLW, pcop0);
11056 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11057 pic16_emitpcode(POC_MOVLW, pcop1);
11058 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11059 pic16_emitpcode(POC_MOVLW, pcop2);
11060 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11063 pic16_emitpcode(POC_MOVLW, pcop0);
11064 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11065 pic16_emitpcode(POC_MOVLW, pcop1);
11066 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11068 pic16_emitpcode(POC_MOVLW, pcop0);
11069 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11073 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11074 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11075 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11076 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11077 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11078 if(AOP_SIZE(result) <2)
11079 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11081 /* if they in different places then copy */
11082 size = AOP_SIZE(result);
11085 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11086 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11093 /* if the result is of type pointer */
11094 if (IS_PTR(ctype)) {
11096 sym_link *type = operandType(right);
11097 sym_link *etype = getSpec(type);
11099 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
11101 /* pointer to generic pointer */
11102 if (IS_GENPTR(ctype)) {
11106 p_type = DCL_TYPE(type);
11108 /* we have to go by the storage class */
11109 p_type = PTR_TYPE(SPEC_OCLS(etype));
11111 /* if (SPEC_OCLS(etype)->codesp ) */
11112 /* p_type = CPOINTER ; */
11114 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11115 /* p_type = FPOINTER ; */
11117 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11118 /* p_type = PPOINTER; */
11120 /* if (SPEC_OCLS(etype) == idata ) */
11121 /* p_type = IPOINTER ; */
11123 /* p_type = POINTER ; */
11126 /* the first two bytes are known */
11127 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
11128 size = GPTRSIZE - 1;
11131 if(offset < AOP_SIZE(right)) {
11132 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
11133 if ((AOP_TYPE(right) == AOP_PCODE) &&
11134 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11135 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11136 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11138 pic16_aopPut(AOP(result),
11139 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11143 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11146 /* the last byte depending on type */
11150 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11153 pic16_emitcode(";BUG!? ","%d",__LINE__);
11157 pic16_emitcode(";BUG!? ","%d",__LINE__);
11161 pic16_emitcode(";BUG!? ","%d",__LINE__);
11166 /* this should never happen */
11167 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11168 "got unknown pointer type");
11171 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
11175 /* just copy the pointers */
11176 size = AOP_SIZE(result);
11179 pic16_aopPut(AOP(result),
11180 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11189 /* so we now know that the size of destination is greater
11190 than the size of the source.
11191 Now, if the next iCode is an operator then we might be
11192 able to optimize the operation without performing a cast.
11194 if(genMixedOperation(ic))
11197 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11199 /* we move to result for the size of source */
11200 size = AOP_SIZE(right);
11203 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11204 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11208 /* now depending on the sign of the destination */
11209 size = AOP_SIZE(result) - AOP_SIZE(right);
11210 /* if unsigned or not an integral type */
11211 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11213 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11215 /* we need to extend the sign :( */
11218 /* Save one instruction of casting char to int */
11219 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11220 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11221 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
11223 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11226 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11228 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
11230 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
11233 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
11238 pic16_freeAsmop(right,NULL,ic,TRUE);
11239 pic16_freeAsmop(result,NULL,ic,TRUE);
11243 /*-----------------------------------------------------------------*/
11244 /* genDjnz - generate decrement & jump if not zero instrucion */
11245 /*-----------------------------------------------------------------*/
11246 static int genDjnz (iCode *ic, iCode *ifx)
11248 symbol *lbl, *lbl1;
11249 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11254 /* if the if condition has a false label
11255 then we cannot save */
11259 /* if the minus is not of the form
11261 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11262 !IS_OP_LITERAL(IC_RIGHT(ic)))
11265 if (operandLitValue(IC_RIGHT(ic)) != 1)
11268 /* if the size of this greater than one then no
11270 if (getSize(operandType(IC_RESULT(ic))) > 1)
11273 /* otherwise we can save BIG */
11274 lbl = newiTempLabel(NULL);
11275 lbl1= newiTempLabel(NULL);
11277 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11279 if (IS_AOP_PREG(IC_RESULT(ic))) {
11280 pic16_emitcode("dec","%s",
11281 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11282 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11283 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11287 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11288 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11290 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11291 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
11294 /* pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11295 /* pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11296 /* pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11297 /* pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11300 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11301 ifx->generated = 1;
11305 /*-----------------------------------------------------------------*/
11306 /* genReceive - generate code for a receive iCode */
11307 /*-----------------------------------------------------------------*/
11308 static void genReceive (iCode *ic)
11310 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11312 if (isOperandInFarSpace(IC_RESULT(ic)) &&
11313 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11314 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11316 int size = getSize(operandType(IC_RESULT(ic)));
11317 int offset = pic16_fReturnSizePic - size;
11320 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11321 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11325 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
11327 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11328 size = AOP_SIZE(IC_RESULT(ic));
11331 pic16_emitcode ("pop","acc");
11332 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11335 DEBUGpic16_emitcode ("; ***","2 %s %d",__FUNCTION__,__LINE__);
11338 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11340 assignResultValue(IC_RESULT(ic), 0);
11343 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11346 /*-----------------------------------------------------------------*/
11347 /* genDummyRead - generate code for dummy read of volatiles */
11348 /*-----------------------------------------------------------------*/
11350 genDummyRead (iCode * ic)
11352 pic16_emitcode ("; genDummyRead","");
11353 pic16_emitcode ("; not implemented","");
11358 /*-----------------------------------------------------------------*/
11359 /* genpic16Code - generate code for pic16 based controllers */
11360 /*-----------------------------------------------------------------*/
11362 * At this point, ralloc.c has gone through the iCode and attempted
11363 * to optimize in a way suitable for a PIC. Now we've got to generate
11364 * PIC instructions that correspond to the iCode.
11366 * Once the instructions are generated, we'll pass through both the
11367 * peep hole optimizer and the pCode optimizer.
11368 *-----------------------------------------------------------------*/
11370 void genpic16Code (iCode *lic)
11375 lineHead = lineCurr = NULL;
11377 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11378 pic16_addpBlock(pb);
11381 /* if debug information required */
11382 if (options.debug && currFunc) {
11384 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11389 for (ic = lic ; ic ; ic = ic->next ) {
11391 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11392 if ( cln != ic->lineno ) {
11393 if ( options.debug ) {
11394 debugFile->writeCLine (ic);
11397 if(!options.noCcodeInAsm) {
11398 pic16_addpCode2pBlock(pb,
11399 pic16_newpCodeCSource(ic->lineno, ic->filename,
11400 printCLine(ic->filename, ic->lineno)));
11406 if(options.iCodeInAsm) {
11408 /* insert here code to print iCode as comment */
11409 l = Safe_strdup(printILine(ic));
11410 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11413 /* if the result is marked as
11414 spilt and rematerializable or code for
11415 this has already been generated then
11417 if (resultRemat(ic) || ic->generated )
11420 /* depending on the operation */
11439 /* IPOP happens only when trying to restore a
11440 spilt live range, if there is an ifx statement
11441 following this pop then the if statement might
11442 be using some of the registers being popped which
11443 would destroy the contents of the register so
11444 we need to check for this condition and handle it */
11446 ic->next->op == IFX &&
11447 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
11448 genIfx (ic->next,ic);
11466 genEndFunction (ic);
11482 pic16_genPlus (ic) ;
11486 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11487 pic16_genMinus (ic);
11503 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
11507 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11514 /* note these two are xlated by algebraic equivalence
11515 during parsing SDCC.y */
11516 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11517 "got '>=' or '<=' shouldn't have come here");
11521 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11533 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11537 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11541 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11565 genRightShift (ic);
11568 case GET_VALUE_AT_ADDRESS:
11573 if (POINTER_SET(ic))
11600 addSet(&_G.sendSet,ic);
11603 case DUMMY_READ_VOLATILE:
11613 /* now we are ready to call the
11614 peep hole optimizer */
11615 if (!options.nopeep) {
11616 peepHole (&lineHead);
11618 /* now do the actual printing */
11619 printLine (lineHead,codeOutFile);
11622 DFPRINTF((stderr,"printing pBlock\n\n"));
11623 pic16_printpBlock(stdout,pb);