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 (strcmp(sym1->rname,sym2->rname) == 0)
853 /* if left is a tmp & right is not */
857 (sym1->usl.spillLoc == sym2))
864 (sym2->usl.spillLoc == sym1))
870 /*-----------------------------------------------------------------*/
871 /* pic16_sameRegs - two asmops have the same registers */
872 /*-----------------------------------------------------------------*/
873 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
880 if (aop1->type != AOP_REG ||
881 aop2->type != AOP_REG )
884 if (aop1->size != aop2->size )
887 for (i = 0 ; i < aop1->size ; i++ )
888 if (aop1->aopu.aop_reg[i] !=
889 aop2->aopu.aop_reg[i] )
895 /*-----------------------------------------------------------------*/
896 /* pic16_aopOp - allocates an asmop for an operand : */
897 /*-----------------------------------------------------------------*/
898 void pic16_aopOp (operand *op, iCode *ic, bool result)
907 // DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
909 /* if this a literal */
910 if (IS_OP_LITERAL(op)) {
911 op->aop = aop = newAsmop(AOP_LIT);
912 aop->aopu.aop_lit = op->operand.valOperand;
913 aop->size = getSize(operandType(op));
918 sym_link *type = operandType(op);
920 if(IS_PTR_CONST(type))
924 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
927 /* if already has a asmop then continue */
931 /* if the underlying symbol has a aop */
932 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
933 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
934 op->aop = OP_SYMBOL(op)->aop;
938 /* if this is a true symbol */
939 if (IS_TRUE_SYMOP(op)) {
940 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
941 op->aop = aopForSym(ic, op, result);
945 /* this is a temporary : this has
951 e) can be a return use only */
955 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
956 /* if the type is a conditional */
957 if (sym->regType == REG_CND) {
958 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
963 /* if it is spilt then two situations
965 b) has a spill location */
966 if (sym->isspilt || sym->nRegs == 0) {
968 DEBUGpic16_emitcode(";","%d",__LINE__);
969 /* rematerialize it NOW */
972 sym->aop = op->aop = aop =
974 aop->size = getSize(sym->type);
975 //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
982 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
983 aop->size = getSize(sym->type);
984 for ( i = 0 ; i < 1 ; i++ ) {
985 aop->aopu.aop_str[i] = accUse[i];
986 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
988 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
989 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
997 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
998 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
999 //pic16_allocDirReg (IC_LEFT(ic));
1000 aop->size = getSize(sym->type);
1005 aop = op->aop = sym->aop = newAsmop(AOP_STR);
1006 aop->size = getSize(sym->type);
1007 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1008 aop->aopu.aop_str[i] = fReturn[i];
1010 DEBUGpic16_emitcode(";","%d",__LINE__);
1014 /* else spill location */
1015 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1016 /* force a new aop if sizes differ */
1017 sym->usl.spillLoc->aop = NULL;
1019 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1020 __FUNCTION__,__LINE__,
1021 sym->usl.spillLoc->rname,
1022 sym->rname, sym->usl.spillLoc->offset);
1024 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1025 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1026 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1028 sym->usl.spillLoc->offset, op);
1029 aop->size = getSize(sym->type);
1035 sym_link *type = operandType(op);
1037 if(IS_PTR_CONST(type))
1039 if(IS_CODEPTR(type))
1041 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1044 /* must be in a register */
1045 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1046 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1047 aop->size = sym->nRegs;
1048 for ( i = 0 ; i < sym->nRegs ;i++)
1049 aop->aopu.aop_reg[i] = sym->regs[i];
1052 /*-----------------------------------------------------------------*/
1053 /* pic16_freeAsmop - free up the asmop given to an operand */
1054 /*----------------------------------------------------------------*/
1055 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1072 /* depending on the asmop type only three cases need work AOP_RO
1073 , AOP_R1 && AOP_STK */
1075 switch (aop->type) {
1079 pic16_emitcode ("pop","ar0");
1083 bitVectUnSetBit(ic->rUsed,R0_IDX);
1089 pic16_emitcode ("pop","ar1");
1093 bitVectUnSetBit(ic->rUsed,R1_IDX);
1099 int stk = aop->aopu.aop_stk + aop->size;
1100 bitVectUnSetBit(ic->rUsed,R0_IDX);
1101 bitVectUnSetBit(ic->rUsed,R1_IDX);
1103 getFreePtr(ic,&aop,FALSE);
1105 if (options.stack10bit)
1107 /* I'm not sure what to do here yet... */
1110 "*** Warning: probably generating bad code for "
1111 "10 bit stack mode.\n");
1115 pic16_emitcode ("mov","a,_bp");
1116 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1117 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1119 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1123 pic16_emitcode("pop","acc");
1124 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1126 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1129 pic16_freeAsmop(op,NULL,ic,TRUE);
1131 pic16_emitcode("pop","ar0");
1136 pic16_emitcode("pop","ar1");
1144 /* all other cases just dealloc */
1148 OP_SYMBOL(op)->aop = NULL;
1149 /* if the symbol has a spill */
1151 SPIL_LOC(op)->aop = NULL;
1156 /*-----------------------------------------------------------------*/
1157 /* pic16_aopGet - for fetching value of the aop */
1158 /*-----------------------------------------------------------------*/
1159 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1164 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1166 /* offset is greater than size then zero */
1167 if (offset > (aop->size - 1) &&
1168 aop->type != AOP_LIT)
1171 /* depending on type */
1172 switch (aop->type) {
1176 DEBUGpic16_emitcode(";","%d",__LINE__);
1177 /* if we need to increment it */
1178 while (offset > aop->coff) {
1179 pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1183 while (offset < aop->coff) {
1184 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1188 aop->coff = offset ;
1190 pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1191 return (dname ? "acc" : "a");
1193 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1194 rs = Safe_calloc(1,strlen(s)+1);
1200 DEBUGpic16_emitcode(";","%d",__LINE__);
1201 if (aop->type == AOP_DPTR2)
1206 while (offset > aop->coff) {
1207 pic16_emitcode ("inc","dptr");
1211 while (offset < aop->coff) {
1212 pic16_emitcode("lcall","__decdptr");
1218 pic16_emitcode("clr","a");
1219 pic16_emitcode("movc","a,@a+dptr");
1222 pic16_emitcode("movx","a,@dptr");
1225 if (aop->type == AOP_DPTR2)
1230 return (dname ? "acc" : "a");
1235 sprintf (s,"%s",aop->aopu.aop_immd);
1238 sprintf(s,"(%s >> %d)",
1243 aop->aopu.aop_immd);
1244 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1245 rs = Safe_calloc(1,strlen(s)+1);
1251 sprintf(s,"(%s + %d)",
1254 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1256 sprintf(s,"%s",aop->aopu.aop_dir);
1257 rs = Safe_calloc(1,strlen(s)+1);
1263 // return aop->aopu.aop_reg[offset]->dname;
1265 return aop->aopu.aop_reg[offset]->name;
1268 //pic16_emitcode(";","%d",__LINE__);
1269 return aop->aopu.aop_dir;
1272 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1273 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1275 return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1278 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1279 rs = Safe_calloc(1,strlen(s)+1);
1284 aop->coff = offset ;
1285 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1288 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1290 return aop->aopu.aop_str[offset];
1294 pCodeOp *pcop = aop->aopu.pcop;
1295 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1297 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1298 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1299 sprintf(s,"%s", pcop->name);
1301 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1304 rs = Safe_calloc(1,strlen(s)+1);
1310 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1311 "aopget got unsupported aop->type");
1316 /*-----------------------------------------------------------------*/
1317 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1318 /*-----------------------------------------------------------------*/
1319 pCodeOp *pic16_popGetTempReg(void)
1324 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1329 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1330 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1331 PCOR(pcop)->r->wasUsed=1;
1332 PCOR(pcop)->r->isFree=0;
1334 /* push value on stack */
1335 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1343 /*-----------------------------------------------------------------*/
1344 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1345 /*-----------------------------------------------------------------*/
1346 void pic16_popReleaseTempReg(pCodeOp *pcop)
1348 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1350 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1351 PCOR(pcop)->r->isFree = 1;
1353 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1356 /*-----------------------------------------------------------------*/
1357 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1358 /*-----------------------------------------------------------------*/
1359 pCodeOp *pic16_popGetLabel(unsigned int key)
1362 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1367 return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1370 /*-----------------------------------------------------------------*/
1371 /* pic16_popCopyReg - copy a pcode operator */
1372 /*-----------------------------------------------------------------*/
1373 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1377 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1378 pcor->pcop.type = pc->pcop.type;
1380 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1381 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1383 pcor->pcop.name = NULL;
1386 pcor->rIdx = pc->rIdx;
1389 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1394 /*-----------------------------------------------------------------*/
1395 /* pic16_popGetLit - asm operator to pcode operator conversion */
1396 /*-----------------------------------------------------------------*/
1397 pCodeOp *pic16_popGetLit(unsigned int lit)
1399 return pic16_newpCodeOpLit(lit);
1402 /*-----------------------------------------------------------------*/
1403 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1404 /*-----------------------------------------------------------------*/
1405 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1407 return pic16_newpCodeOpLit2(lit, arg2);
1411 /*-----------------------------------------------------------------*/
1412 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1413 /*-----------------------------------------------------------------*/
1414 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1416 return pic16_newpCodeOpImmd(name, offset,index, 0);
1420 /*-----------------------------------------------------------------*/
1421 /* pic16_popGet - asm operator to pcode operator conversion */
1422 /*-----------------------------------------------------------------*/
1423 pCodeOp *pic16_popGetWithString(char *str)
1429 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1433 pcop = pic16_newpCodeOp(str,PO_STR);
1438 /*-----------------------------------------------------------------*/
1439 /* pic16_popRegFromString - */
1440 /*-----------------------------------------------------------------*/
1441 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1444 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1445 pcop->type = PO_DIR;
1447 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1448 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1453 pcop->name = Safe_calloc(1,strlen(str)+1);
1454 strcpy(pcop->name,str);
1456 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1458 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1459 if(PCOR(pcop)->r == NULL) {
1460 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1461 // __FUNCTION__, __LINE__, str, size, offset);
1462 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1464 //fprintf(stderr, "allocating new register -> %s\n", str);
1466 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1468 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d",__LINE__,pcop->name,size,offset);
1470 PCOR(pcop)->instance = offset;
1475 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1479 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1481 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1482 PCOR(pcop)->rIdx = rIdx;
1483 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1484 PCOR(pcop)->r->isFree = 0;
1485 PCOR(pcop)->r->wasUsed = 1;
1487 pcop->type = PCOR(pcop)->r->pc_type;
1492 /*---------------------------------------------------------------------------------*/
1493 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1495 /*---------------------------------------------------------------------------------*/
1496 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1501 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1503 /* comment the following check, so errors to throw up */
1504 // if(!pcop2)return NULL;
1506 temp = pic16_popGet(aop_dst, offset);
1507 pcop2->pcop2 = temp;
1514 /*--------------------------------------------------------------------------------.-*/
1515 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1516 /* VR 030601 , adapted by Hans Dorn */
1517 /*--------------------------------------------------------------------------------.-*/
1518 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1522 pcop2 = (pCodeOpReg2 *)src;
1530 /*---------------------------------------------------------------------------------*/
1531 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1532 /* movff instruction */
1533 /*---------------------------------------------------------------------------------*/
1534 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1539 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1540 pcop2->pcop2 = pic16_popCopyReg(dst);
1542 /* the pCodeOp may be already allocated */
1543 pcop2 = (pCodeOpReg2 *)(src);
1544 pcop2->pcop2 = (pCodeOp *)(dst);
1551 /*-----------------------------------------------------------------*/
1552 /* pic16_popGet - asm operator to pcode operator conversion */
1553 /*-----------------------------------------------------------------*/
1554 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1556 //char *s = buffer ;
1560 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1561 /* offset is greater than
1564 // if (offset > (aop->size - 1) &&
1565 // aop->type != AOP_LIT)
1566 // return NULL; //zero;
1568 /* depending on type */
1569 switch (aop->type) {
1575 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1576 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1583 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1584 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1588 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1590 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1592 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1594 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1595 PCOR(pcop)->rIdx = rIdx;
1596 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1597 PCOR(pcop)->r->wasUsed=1;
1598 PCOR(pcop)->r->isFree=0;
1600 PCOR(pcop)->instance = offset;
1601 pcop->type = PCOR(pcop)->r->pc_type;
1602 // rs = aop->aopu.aop_reg[offset]->name;
1603 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1607 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1608 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1614 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1615 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1619 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1621 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1623 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1624 PCOR(pcop)->rIdx = rIdx;
1625 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1626 PCOR(pcop)->r->wasUsed=1;
1627 PCOR(pcop)->r->isFree=0;
1629 PCOR(pcop)->instance = offset;
1630 pcop->type = PCOR(pcop)->r->pc_type;
1631 rs = aop->aopu.aop_reg[offset]->name;
1632 DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1637 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1639 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1640 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1641 //if(PCOR(pcop)->r == NULL)
1642 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1646 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1647 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1650 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1651 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1654 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1655 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1656 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1657 pcop->type = PCOR(pcop)->r->pc_type;
1658 pcop->name = PCOR(pcop)->r->name;
1664 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1666 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1667 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1669 switch( aop->aopu.pcop->type ) {
1670 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1671 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1673 assert( 0 ); /* should never reach here */;
1676 PCOI(pcop)->offset = offset;
1681 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1682 "pic16_popGet got unsupported aop->type");
1685 /*-----------------------------------------------------------------*/
1686 /* pic16_aopPut - puts a string for a aop */
1687 /*-----------------------------------------------------------------*/
1688 void pic16_aopPut (asmop *aop, char *s, int offset)
1693 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1695 if (aop->size && offset > ( aop->size - 1)) {
1696 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1697 "pic16_aopPut got offset > aop->size");
1701 /* will assign value to value */
1702 /* depending on where it is ofcourse */
1703 switch (aop->type) {
1706 sprintf(d,"(%s + %d)",
1707 aop->aopu.aop_dir,offset);
1708 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1711 sprintf(d,"%s",aop->aopu.aop_dir);
1714 DEBUGpic16_emitcode(";","%d",__LINE__);
1716 pic16_emitcode("movf","%s,w",s);
1717 pic16_emitcode("movwf","%s",d);
1720 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1721 if(offset >= aop->size) {
1722 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1725 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1728 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1735 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1736 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1739 strcmp(s,"r0") == 0 ||
1740 strcmp(s,"r1") == 0 ||
1741 strcmp(s,"r2") == 0 ||
1742 strcmp(s,"r3") == 0 ||
1743 strcmp(s,"r4") == 0 ||
1744 strcmp(s,"r5") == 0 ||
1745 strcmp(s,"r6") == 0 ||
1746 strcmp(s,"r7") == 0 )
1747 pic16_emitcode("mov","%s,%s ; %d",
1748 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1752 if(strcmp(s,"W")==0 )
1753 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
1755 pic16_emitcode("movwf","%s",
1756 aop->aopu.aop_reg[offset]->name);
1758 if(strcmp(s,zero)==0) {
1759 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1761 } else if(strcmp(s,"W")==0) {
1762 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1763 pcop->type = PO_GPR_REGISTER;
1765 PCOR(pcop)->rIdx = -1;
1766 PCOR(pcop)->r = NULL;
1768 DEBUGpic16_emitcode(";","%d",__LINE__);
1769 pcop->name = Safe_strdup(s);
1770 pic16_emitpcode(POC_MOVFW,pcop);
1771 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1772 } else if(strcmp(s,one)==0) {
1773 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1774 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1776 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1784 if (aop->type == AOP_DPTR2)
1790 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1791 "pic16_aopPut writting to code space");
1795 while (offset > aop->coff) {
1797 pic16_emitcode ("inc","dptr");
1800 while (offset < aop->coff) {
1802 pic16_emitcode("lcall","__decdptr");
1807 /* if not in accumulater */
1810 pic16_emitcode ("movx","@dptr,a");
1812 if (aop->type == AOP_DPTR2)
1820 while (offset > aop->coff) {
1822 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1824 while (offset < aop->coff) {
1826 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1832 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1837 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1839 if (strcmp(s,"r0") == 0 ||
1840 strcmp(s,"r1") == 0 ||
1841 strcmp(s,"r2") == 0 ||
1842 strcmp(s,"r3") == 0 ||
1843 strcmp(s,"r4") == 0 ||
1844 strcmp(s,"r5") == 0 ||
1845 strcmp(s,"r6") == 0 ||
1846 strcmp(s,"r7") == 0 ) {
1848 sprintf(buffer,"a%s",s);
1849 pic16_emitcode("mov","@%s,%s",
1850 aop->aopu.aop_ptr->name,buffer);
1852 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1857 if (strcmp(s,"a") == 0)
1858 pic16_emitcode("push","acc");
1860 pic16_emitcode("push","%s",s);
1865 /* if bit variable */
1866 if (!aop->aopu.aop_dir) {
1867 pic16_emitcode("clr","a");
1868 pic16_emitcode("rlc","a");
1871 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1874 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1877 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1879 lbl = newiTempLabel(NULL);
1881 if (strcmp(s,"a")) {
1884 pic16_emitcode("clr","c");
1885 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1886 pic16_emitcode("cpl","c");
1887 pic16_emitcode("","%05d_DS_:",lbl->key+100);
1888 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1895 if (strcmp(aop->aopu.aop_str[offset],s))
1896 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1901 if (!offset && (strcmp(s,"acc") == 0))
1904 if (strcmp(aop->aopu.aop_str[offset],s))
1905 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1909 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1910 "pic16_aopPut got unsupported aop->type");
1916 /*-----------------------------------------------------------------*/
1917 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1918 /*-----------------------------------------------------------------*/
1919 static void mov2w (asmop *aop, int offset)
1925 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1928 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1930 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1935 /* push pcop into stack */
1936 void pic16_pushpCodeOp(pCodeOp *pcop)
1938 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1939 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1942 /* pop pcop from stack */
1943 void pic16_poppCodeOp(pCodeOp *pcop)
1945 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1949 /*-----------------------------------------------------------------*/
1950 /* pushw - pushes wreg to stack */
1951 /*-----------------------------------------------------------------*/
1954 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1955 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1959 /*-----------------------------------------------------------------*/
1960 /* pushaop - pushes aop to stack */
1961 /*-----------------------------------------------------------------*/
1962 void pushaop(asmop *aop, int offset)
1964 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1965 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1968 /*-----------------------------------------------------------------*/
1969 /* popaop - pops aop from stack */
1970 /*-----------------------------------------------------------------*/
1971 void popaop(asmop *aop, int offset)
1973 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
1974 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1977 void popaopidx(asmop *aop, int offset, int index)
1981 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1983 if(STACK_MODEL_LARGE)ofs++;
1985 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1986 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1989 /*-----------------------------------------------------------------*/
1990 /* reAdjustPreg - points a register back to where it should */
1991 /*-----------------------------------------------------------------*/
1992 static void reAdjustPreg (asmop *aop)
1996 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1998 if ((size = aop->size) <= 1)
2001 switch (aop->type) {
2005 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2009 if (aop->type == AOP_DPTR2)
2015 pic16_emitcode("lcall","__decdptr");
2018 if (aop->type == AOP_DPTR2)
2030 /*-----------------------------------------------------------------*/
2031 /* opIsGptr: returns non-zero if the passed operand is */
2032 /* a generic pointer type. */
2033 /*-----------------------------------------------------------------*/
2034 static int opIsGptr(operand *op)
2036 sym_link *type = operandType(op);
2038 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2039 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2047 /*-----------------------------------------------------------------*/
2048 /* pic16_getDataSize - get the operand data size */
2049 /*-----------------------------------------------------------------*/
2050 int pic16_getDataSize(operand *op)
2052 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2055 return AOP_SIZE(op);
2057 // tsd- in the pic port, the genptr size is 1, so this code here
2058 // fails. ( in the 8051 port, the size was 4).
2061 size = AOP_SIZE(op);
2062 if (size == GPTRSIZE)
2064 sym_link *type = operandType(op);
2065 if (IS_GENPTR(type))
2067 /* generic pointer; arithmetic operations
2068 * should ignore the high byte (pointer type).
2071 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2078 /*-----------------------------------------------------------------*/
2079 /* pic16_outAcc - output Acc */
2080 /*-----------------------------------------------------------------*/
2081 void pic16_outAcc(operand *result)
2084 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2085 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2088 size = pic16_getDataSize(result);
2090 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2093 /* unsigned or positive */
2095 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2100 /*-----------------------------------------------------------------*/
2101 /* pic16_outBitC - output a bit C */
2102 /* Move to result the value of Carry flag -- VR */
2103 /*-----------------------------------------------------------------*/
2104 void pic16_outBitC(operand *result)
2108 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2109 /* if the result is bit */
2110 if (AOP_TYPE(result) == AOP_CRY) {
2111 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2112 pic16_aopPut(AOP(result),"c",0);
2115 i = AOP_SIZE(result);
2117 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2119 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2122 pic16_emitcode("clr","a ; %d", __LINE__);
2123 pic16_emitcode("rlc","a");
2124 pic16_outAcc(result);
2129 /*-----------------------------------------------------------------*/
2130 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2131 /*-----------------------------------------------------------------*/
2132 void pic16_toBoolean(operand *oper)
2134 int size = AOP_SIZE(oper) - 1;
2137 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2139 if ( AOP_TYPE(oper) != AOP_ACC) {
2140 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2143 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2148 #if !defined(GEN_Not)
2149 /*-----------------------------------------------------------------*/
2150 /* genNot - generate code for ! operation */
2151 /*-----------------------------------------------------------------*/
2152 static void pic16_genNot (iCode *ic)
2157 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2158 /* assign asmOps to operand & result */
2159 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2160 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2162 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2163 /* if in bit space then a special case */
2164 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2165 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2166 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2167 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2169 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2170 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2171 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2176 size = AOP_SIZE(IC_LEFT(ic));
2178 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2179 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2180 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2183 pic16_toBoolean(IC_LEFT(ic));
2185 tlbl = newiTempLabel(NULL);
2186 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2187 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2188 pic16_outBitC(IC_RESULT(ic));
2191 /* release the aops */
2192 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2193 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2198 #if !defined(GEN_Cpl)
2199 /*-----------------------------------------------------------------*/
2200 /* genCpl - generate code for complement */
2201 /*-----------------------------------------------------------------*/
2202 static void pic16_genCpl (iCode *ic)
2208 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2209 /* assign asmOps to operand & result */
2210 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2211 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2213 /* if both are in bit space then
2215 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2216 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2218 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2219 pic16_emitcode("cpl","c");
2220 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2224 size = AOP_SIZE(IC_RESULT(ic));
2227 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2229 pic16_emitcode("cpl","a");
2230 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2232 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2233 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2235 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2236 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2244 /* release the aops */
2245 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2246 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2250 /*-----------------------------------------------------------------*/
2251 /* genUminusFloat - unary minus for floating points */
2252 /*-----------------------------------------------------------------*/
2253 static void genUminusFloat(operand *op,operand *result)
2255 int size ,offset =0 ;
2258 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2259 /* for this we just need to flip the
2260 first it then copy the rest in place */
2261 size = AOP_SIZE(op) - 1;
2262 l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2266 pic16_emitcode("cpl","acc.7");
2267 pic16_aopPut(AOP(result),"a",3);
2270 pic16_aopPut(AOP(result),
2271 pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2277 /*-----------------------------------------------------------------*/
2278 /* genUminus - unary minus code generation */
2279 /*-----------------------------------------------------------------*/
2280 static void genUminus (iCode *ic)
2283 sym_link *optype, *rtype;
2285 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2288 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2289 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2291 /* if both in bit space then special case */
2292 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2293 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2295 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2296 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2297 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2302 optype = operandType(IC_LEFT(ic));
2303 rtype = operandType(IC_RESULT(ic));
2305 /* if float then do float stuff */
2306 if (IS_FLOAT(optype)) {
2307 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2311 /* otherwise subtract from zero by taking the 2's complement */
2312 size = AOP_SIZE(IC_LEFT(ic));
2314 for(i=0; i<size; i++) {
2315 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2316 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)),i));
2318 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2319 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2323 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2324 for(i=1; i<size; i++) {
2326 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2330 /* release the aops */
2331 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2332 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2335 /*-----------------------------------------------------------------*/
2336 /* saveRegisters - will look for a call and save the registers */
2337 /*-----------------------------------------------------------------*/
2338 static void saveRegisters(iCode *lic)
2345 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2347 for (ic = lic ; ic ; ic = ic->next)
2348 if (ic->op == CALL || ic->op == PCALL)
2352 fprintf(stderr,"found parameter push with no function call\n");
2356 /* if the registers have been saved already then
2358 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2361 /* find the registers in use at this time
2362 and push them away to safety */
2363 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2367 if (options.useXstack) {
2368 if (bitVectBitValue(rsave,R0_IDX))
2369 pic16_emitcode("mov","b,r0");
2370 pic16_emitcode("mov","r0,%s",spname);
2371 for (i = 0 ; i < pic16_nRegs ; i++) {
2372 if (bitVectBitValue(rsave,i)) {
2374 pic16_emitcode("mov","a,b");
2376 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2377 pic16_emitcode("movx","@r0,a");
2378 pic16_emitcode("inc","r0");
2381 pic16_emitcode("mov","%s,r0",spname);
2382 if (bitVectBitValue(rsave,R0_IDX))
2383 pic16_emitcode("mov","r0,b");
2385 //for (i = 0 ; i < pic16_nRegs ; i++) {
2386 // if (bitVectBitValue(rsave,i))
2387 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2390 dtype = operandType(IC_LEFT(ic));
2391 if (currFunc && dtype &&
2392 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2393 IFFUNC_ISISR(currFunc->type) &&
2396 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2399 /*-----------------------------------------------------------------*/
2400 /* unsaveRegisters - pop the pushed registers */
2401 /*-----------------------------------------------------------------*/
2402 static void unsaveRegisters (iCode *ic)
2407 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2408 /* find the registers in use at this time
2409 and push them away to safety */
2410 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2413 if (options.useXstack) {
2414 pic16_emitcode("mov","r0,%s",spname);
2415 for (i = pic16_nRegs ; i >= 0 ; i--) {
2416 if (bitVectBitValue(rsave,i)) {
2417 pic16_emitcode("dec","r0");
2418 pic16_emitcode("movx","a,@r0");
2420 pic16_emitcode("mov","b,a");
2422 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2426 pic16_emitcode("mov","%s,r0",spname);
2427 if (bitVectBitValue(rsave,R0_IDX))
2428 pic16_emitcode("mov","r0,b");
2430 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2431 // if (bitVectBitValue(rsave,i))
2432 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2438 /*-----------------------------------------------------------------*/
2440 /*-----------------------------------------------------------------*/
2441 static void pushSide(operand * oper, int size)
2444 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2446 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2447 if (AOP_TYPE(oper) != AOP_REG &&
2448 AOP_TYPE(oper) != AOP_DIR &&
2450 pic16_emitcode("mov","a,%s",l);
2451 pic16_emitcode("push","acc");
2453 pic16_emitcode("push","%s",l);
2458 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2460 // (AOP(left)->aopu.pcop->type == PO_DIR)?
2462 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2463 pic16_emitpcode(POC_MOVFW, src);
2464 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2466 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2467 src, pic16_popGet(AOP(op), offset)));
2472 /*-----------------------------------------------------------------*/
2473 /* assignResultValue - assign results to oper, rescall==1 is */
2474 /* called from genCall() or genPCall() */
2475 /*-----------------------------------------------------------------*/
2476 static void assignResultValue(operand * oper, int rescall)
2478 int size = AOP_SIZE(oper);
2480 DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2481 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2484 /* assign result from a call/pcall function() */
2486 /* function results are stored in a special order,
2487 * see top of file with Function return policy, or manual */
2490 /* 8-bits, result in WREG */
2491 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2494 /* 16-bits, result in PRODL:WREG */
2495 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2499 /* 24-bits, result in PRODH:PRODL:WREG */
2500 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2504 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2505 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2508 /* >32-bits, result on stack, and FSR0 points to beginning.
2509 * Fix stack when done */
2512 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2513 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2515 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2520 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2521 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2522 if(STACK_MODEL_LARGE) {
2524 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2528 if(!GpsuedoStkPtr) {
2529 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2530 /* The last byte in the assignment is in W */
2532 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2537 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2538 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2540 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2546 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2548 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2558 /*-----------------------------------------------------------------*/
2559 /* genIpush - genrate code for pushing this gets a little complex */
2560 /*-----------------------------------------------------------------*/
2561 static void genIpush (iCode *ic)
2564 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2566 int size, offset = 0 ;
2570 /* if this is not a parm push : ie. it is spill push
2571 and spill push is always done on the local stack */
2572 if (!ic->parmPush) {
2574 /* and the item is spilt then do nothing */
2575 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2578 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2579 size = AOP_SIZE(IC_LEFT(ic));
2580 /* push it on the stack */
2582 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2587 pic16_emitcode("push","%s",l);
2592 /* this is a paramter push: in this case we call
2593 the routine to find the call and save those
2594 registers that need to be saved */
2597 /* then do the push */
2598 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2601 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2602 size = AOP_SIZE(IC_LEFT(ic));
2605 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2606 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2607 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2609 pic16_emitcode("mov","a,%s",l);
2610 pic16_emitcode("push","acc");
2612 pic16_emitcode("push","%s",l);
2615 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2619 /*-----------------------------------------------------------------*/
2620 /* genIpop - recover the registers: can happen only for spilling */
2621 /*-----------------------------------------------------------------*/
2622 static void genIpop (iCode *ic)
2624 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2629 /* if the temp was not pushed then */
2630 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2633 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2634 size = AOP_SIZE(IC_LEFT(ic));
2637 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2640 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2644 /*-----------------------------------------------------------------*/
2645 /* unsaverbank - restores the resgister bank from stack */
2646 /*-----------------------------------------------------------------*/
2647 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2649 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2655 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2657 if (options.useXstack) {
2659 r = getFreePtr(ic,&aop,FALSE);
2662 pic16_emitcode("mov","%s,_spx",r->name);
2663 pic16_emitcode("movx","a,@%s",r->name);
2664 pic16_emitcode("mov","psw,a");
2665 pic16_emitcode("dec","%s",r->name);
2668 pic16_emitcode ("pop","psw");
2671 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2672 if (options.useXstack) {
2673 pic16_emitcode("movx","a,@%s",r->name);
2674 //pic16_emitcode("mov","(%s+%d),a",
2675 // regspic16[i].base,8*bank+regspic16[i].offset);
2676 pic16_emitcode("dec","%s",r->name);
2679 pic16_emitcode("pop",""); //"(%s+%d)",
2680 //regspic16[i].base,8*bank); //+regspic16[i].offset);
2683 if (options.useXstack) {
2685 pic16_emitcode("mov","_spx,%s",r->name);
2686 pic16_freeAsmop(NULL,aop,ic,TRUE);
2692 /*-----------------------------------------------------------------*/
2693 /* saverbank - saves an entire register bank on the stack */
2694 /*-----------------------------------------------------------------*/
2695 static void saverbank (int bank, iCode *ic, bool pushPsw)
2697 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2703 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2704 if (options.useXstack) {
2707 r = getFreePtr(ic,&aop,FALSE);
2708 pic16_emitcode("mov","%s,_spx",r->name);
2712 for (i = 0 ; i < pic16_nRegs ;i++) {
2713 if (options.useXstack) {
2714 pic16_emitcode("inc","%s",r->name);
2715 //pic16_emitcode("mov","a,(%s+%d)",
2716 // regspic16[i].base,8*bank+regspic16[i].offset);
2717 pic16_emitcode("movx","@%s,a",r->name);
2719 pic16_emitcode("push","");// "(%s+%d)",
2720 //regspic16[i].base,8*bank+regspic16[i].offset);
2724 if (options.useXstack) {
2725 pic16_emitcode("mov","a,psw");
2726 pic16_emitcode("movx","@%s,a",r->name);
2727 pic16_emitcode("inc","%s",r->name);
2728 pic16_emitcode("mov","_spx,%s",r->name);
2729 pic16_freeAsmop (NULL,aop,ic,TRUE);
2732 pic16_emitcode("push","psw");
2734 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2742 /*-----------------------------------------------------------------*/
2743 /* genCall - generates a call statement */
2744 /*-----------------------------------------------------------------*/
2745 static void genCall (iCode *ic)
2750 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2752 /* if caller saves & we have not saved then */
2756 /* if we are calling a function that is not using
2757 * the same register bank then we need to save the
2758 * destination registers on the stack */
2759 dtype = operandType(IC_LEFT(ic));
2760 if (currFunc && dtype &&
2761 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2762 IFFUNC_ISISR(currFunc->type) &&
2765 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2767 /* if send set is not empty the assign */
2771 /* For the Pic port, there is no data stack.
2772 * So parameters passed to functions are stored
2773 * in registers. (The pCode optimizer will get
2774 * rid of most of these :). */
2776 int psuedoStkPtr=-1;
2777 int firstTimeThruLoop = 1;
2779 _G.sendSet = reverseSet(_G.sendSet);
2781 /* First figure how many parameters are getting passed */
2782 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2783 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2784 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2785 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2788 stackParms = psuedoStkPtr;
2790 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2791 int size, offset = 0;
2793 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2794 size = AOP_SIZE(IC_LEFT(sic));
2797 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2798 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2799 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2801 if(!firstTimeThruLoop) {
2802 /* If this is not the first time we've been through the loop
2803 * then we need to save the parameter in a temporary
2804 * register. The last byte of the last parameter is
2808 --psuedoStkPtr; // sanity check
2811 firstTimeThruLoop=0;
2813 mov2w (AOP(IC_LEFT(sic)), offset);
2816 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2822 pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2823 OP_SYMBOL(IC_LEFT(ic))->rname :
2824 OP_SYMBOL(IC_LEFT(ic))->name));
2827 /* if we need assign a result value */
2828 if ((IS_ITEMP(IC_RESULT(ic)) &&
2829 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2830 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2831 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2834 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2837 assignResultValue(IC_RESULT(ic), 1);
2839 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2840 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2842 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2846 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2847 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2848 if(STACK_MODEL_LARGE) {
2850 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2854 /* adjust the stack for parameters if required */
2855 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2857 if (ic->parmBytes) {
2860 if (ic->parmBytes > 3) {
2861 pic16_emitcode("mov","a,%s",spname);
2862 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2863 pic16_emitcode("mov","%s,a",spname);
2865 for ( i = 0 ; i < ic->parmBytes ;i++)
2866 pic16_emitcode("dec","%s",spname);
2870 /* if register bank was saved then pop them */
2872 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2874 /* if we hade saved some registers then unsave them */
2875 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2876 unsaveRegisters (ic);
2882 /*-----------------------------------------------------------------*/ // patch 14
2883 /* genPcall - generates a call by pointer statement */
2884 /*-----------------------------------------------------------------*/
2886 // new version, created from genCall
2888 static void genPcall (iCode *ic)
2892 symbol *retlbl = newiTempLabel(NULL);
2893 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2895 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2897 /* if caller saves & we have not saved then */
2901 /* if we are calling a function that is not using
2902 * the same register bank then we need to save the
2903 * destination registers on the stack */
2904 dtype = operandType(IC_LEFT(ic));
2905 if (currFunc && dtype &&
2906 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2907 IFFUNC_ISISR(currFunc->type) &&
2910 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2912 /* if send set is not empty the assign */
2916 /* For the Pic port, there is no data stack.
2917 * So parameters passed to functions are stored
2918 * in registers. (The pCode optimizer will get
2919 * rid of most of these :). */
2921 int psuedoStkPtr=-1;
2922 int firstTimeThruLoop = 1;
2924 _G.sendSet = reverseSet(_G.sendSet);
2926 /* First figure how many parameters are getting passed */
2927 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2928 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2929 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2930 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2933 stackParms = psuedoStkPtr;
2935 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2936 int size, offset = 0;
2938 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2939 size = AOP_SIZE(IC_LEFT(sic));
2942 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2943 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2944 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2946 if(!firstTimeThruLoop) {
2947 /* If this is not the first time we've been through the loop
2948 * then we need to save the parameter in a temporary
2949 * register. The last byte of the last parameter is
2953 --psuedoStkPtr; // sanity check
2956 firstTimeThruLoop=0;
2958 mov2w (AOP(IC_LEFT(sic)), offset);
2961 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2966 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2968 // push return address
2969 // push $ on return stack, then replace with retlbl
2971 pic16_emitpcodeNULLop(POC_PUSH);
2973 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2974 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2975 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2976 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2977 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2978 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2980 /* make the call by writing the pointer into pc */
2981 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
2982 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
2984 // note: MOVFF to PCL not allowed
2985 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
2986 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2989 // pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key));
2990 // pic16_emitpcodeNULLop(POC_NOP);
2991 // pic16_emitpcodeNULLop(POC_NOP);
2993 /* return address is here: (X) */
2994 pic16_emitpLabelFORCE(retlbl->key);
2996 // pic16_emitpcodeNULLop(POC_NOP);
2998 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3001 /* if we need assign a result value */
3002 if ((IS_ITEMP(IC_RESULT(ic)) &&
3003 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3004 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
3005 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3008 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3011 assignResultValue(IC_RESULT(ic), 1);
3013 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3014 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3016 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3020 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3021 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3022 if(STACK_MODEL_LARGE) {
3024 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3028 /* adjust the stack for parameters if required */
3029 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3031 if (ic->parmBytes) {
3034 if (ic->parmBytes > 3) {
3035 pic16_emitcode("mov","a,%s",spname);
3036 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3037 pic16_emitcode("mov","%s,a",spname);
3039 for ( i = 0 ; i < ic->parmBytes ;i++)
3040 pic16_emitcode("dec","%s",spname);
3043 /* if register bank was saved then pop them */
3045 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3047 /* if we hade saved some registers then unsave them */
3048 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3049 unsaveRegisters (ic);
3054 // old version, kept for reference
3056 /*-----------------------------------------------------------------*/
3057 /* genPcall - generates a call by pointer statement */
3058 /*-----------------------------------------------------------------*/
3059 static void genPcall (iCode *ic)
3062 symbol *rlbl = newiTempLabel(NULL);
3065 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3066 /* if caller saves & we have not saved then */
3070 /* if we are calling a function that is not using
3071 the same register bank then we need to save the
3072 destination registers on the stack */
3073 dtype = operandType(IC_LEFT(ic));
3074 if (currFunc && dtype &&
3075 IFFUNC_ISISR(currFunc->type) &&
3076 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3077 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3080 /* push the return address on to the stack */
3081 pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3082 pic16_emitcode("push","acc");
3083 pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3084 pic16_emitcode("push","acc");
3086 if (options.model == MODEL_FLAT24)
3088 pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3089 pic16_emitcode("push","acc");
3092 /* now push the calling address */
3093 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3095 pushSide(IC_LEFT(ic), FPTRSIZE);
3097 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3099 /* if send set is not empty the assign */
3103 for (sic = setFirstItem(_G.sendSet) ; sic ;
3104 sic = setNextItem(_G.sendSet)) {
3105 int size, offset = 0;
3106 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3107 size = AOP_SIZE(IC_LEFT(sic));
3109 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3111 if (strcmp(l,fReturn[offset]))
3112 pic16_emitcode("mov","%s,%s",
3117 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3122 pic16_emitcode("ret","");
3123 pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3126 /* if we need assign a result value */
3127 if ((IS_ITEMP(IC_RESULT(ic)) &&
3128 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3129 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3130 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3133 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3136 assignResultValue(IC_RESULT(ic), 1);
3138 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3141 /* adjust the stack for parameters if
3143 if (ic->parmBytes) {
3145 if (ic->parmBytes > 3) {
3146 pic16_emitcode("mov","a,%s",spname);
3147 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3148 pic16_emitcode("mov","%s,a",spname);
3150 for ( i = 0 ; i < ic->parmBytes ;i++)
3151 pic16_emitcode("dec","%s",spname);
3155 /* if register bank was saved then unsave them */
3156 if (currFunc && dtype &&
3157 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3158 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3160 /* if we hade saved some registers then
3163 unsaveRegisters (ic);
3169 /*-----------------------------------------------------------------*/
3170 /* resultRemat - result is rematerializable */
3171 /*-----------------------------------------------------------------*/
3172 static int resultRemat (iCode *ic)
3174 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3175 if (SKIP_IC(ic) || ic->op == IFX)
3178 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3179 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3180 if (sym->remat && !POINTER_SET(ic))
3187 #if defined(__BORLANDC__) || defined(_MSC_VER)
3188 #define STRCASECMP stricmp
3190 #define STRCASECMP strcasecmp
3194 /*-----------------------------------------------------------------*/
3195 /* inExcludeList - return 1 if the string is in exclude Reg list */
3196 /*-----------------------------------------------------------------*/
3197 static bool inExcludeList(char *s)
3199 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3202 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3203 if (options.excludeRegs[i] &&
3204 STRCASECMP(options.excludeRegs[i],"none") == 0)
3207 for ( i = 0 ; options.excludeRegs[i]; i++) {
3208 if (options.excludeRegs[i] &&
3209 STRCASECMP(s,options.excludeRegs[i]) == 0)
3216 /*-----------------------------------------------------------------*/
3217 /* genFunction - generated code for function entry */
3218 /*-----------------------------------------------------------------*/
3219 static void genFunction (iCode *ic)
3224 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
3226 labelOffset += (max_key+4);
3231 ftype = operandType(IC_LEFT(ic));
3232 sym = OP_SYMBOL(IC_LEFT(ic));
3234 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3235 /* create an absolute section at the interrupt vector:
3236 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3244 sym = OP_SYMBOL( IC_LEFT(ic));
3246 if(interrupts[i]->name
3247 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3254 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3255 __FILE__, __LINE__, sym->name);
3258 _G.interruptvector = found;
3261 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3262 asym = newSymbol(asymname, 0);
3264 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3265 pic16_addpBlock( apb );
3267 pic16_addpCode2pBlock(apb,
3268 pic16_newpCodeCharP(";-----------------------------------------"));
3271 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3273 pic16_addpCode2pBlock(apb,
3274 pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3276 /* mark the end of this tiny function */
3277 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3282 abSym = Safe_calloc(1, sizeof(absSym));
3283 abSym->name = Safe_strdup( asymname );
3285 switch( _G.interruptvector ) {
3286 case 0: abSym->address = 0x000000; break;
3287 case 1: abSym->address = 0x000008; break;
3288 case 2: abSym->address = 0x000018; break;
3291 addSet(&absSymSet, abSym);
3296 /* create the function header */
3297 pic16_emitcode(";","-----------------------------------------");
3298 pic16_emitcode(";"," function %s",sym->name);
3299 pic16_emitcode(";","-----------------------------------------");
3301 pic16_emitcode("","%s:",sym->rname);
3302 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3308 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3309 if(!strcmp(ab->name, sym->name)) {
3310 pic16_pBlockConvert2Absolute(pb);
3317 if(IFFUNC_ISNAKED(ftype)) {
3318 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3322 /* if critical function then turn interrupts off */
3323 if (IFFUNC_ISCRITICAL(ftype))
3324 pic16_emitcode("clr","ea");
3326 /* if this is an interrupt service routine then
3327 * save acc, b, dpl, dph */
3328 if (IFFUNC_ISISR(sym->type)) {
3330 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3331 if(!(_G.interruptvector == 1)) {
3333 /* do not save WREG,STATUS,BSR for high priority interrupts
3334 * because they are stored in the hardware shadow registers already */
3336 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3337 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3338 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3341 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3342 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3343 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3344 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3346 // pic16_pBlockConvert2ISR(pb);
3348 /* if any registers used */
3349 if (sym->regsUsed) {
3350 /* save the registers used */
3351 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3352 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3353 if (bitVectBitValue(sym->regsUsed,i)) {
3354 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3355 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3356 // pic16_regWithIdx(i)->name);
3358 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3364 /* emit code to setup stack frame if user enabled,
3365 * and function is not main() */
3367 // fprintf(stderr, "function name: %s\n", sym->name);
3368 if(strcmp(sym->name, "main")) {
3369 if(/*!options.ommitFramePtr || */sym->regsUsed) {
3370 /* setup the stack frame */
3371 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3372 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3373 if(STACK_MODEL_LARGE)
3374 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3378 /* if callee-save to be used for this function
3379 * then save the registers being used in this function */
3380 // if (IFFUNC_CALLEESAVES(sym->type))
3384 // fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3386 // pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3388 /* if any registers used */
3389 if (sym->regsUsed) {
3390 /* save the registers used */
3391 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3392 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3393 if (bitVectBitValue(sym->regsUsed,i)) {
3395 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3396 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3397 // pic16_regWithIdx(i)->name);
3399 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3401 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3402 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3403 // &pic16_pc_postdec1, 0));
3415 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3417 if (options.useXstack) {
3418 pic16_emitcode("mov","r0,%s",spname);
3419 pic16_emitcode("mov","a,_bp");
3420 pic16_emitcode("movx","@r0,a");
3421 pic16_emitcode("inc","%s",spname);
3423 /* set up the stack */
3424 pic16_emitcode ("push","_bp"); /* save the callers stack */
3426 pic16_emitcode ("mov","_bp,%s",spname);
3429 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3431 /* adjust the stack for the function */
3436 werror(W_STACK_OVERFLOW,sym->name);
3438 if (i > 3 && sym->recvSize < 4) {
3439 pic16_emitcode ("mov","a,sp");
3440 pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3441 pic16_emitcode ("mov","sp,a");
3444 pic16_emitcode("inc","sp");
3448 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3450 pic16_emitcode ("mov","a,_spx");
3451 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3452 pic16_emitcode ("mov","_spx,a");
3457 /*-----------------------------------------------------------------*/
3458 /* genEndFunction - generates epilogue for functions */
3459 /*-----------------------------------------------------------------*/
3460 static void genEndFunction (iCode *ic)
3462 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3464 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3466 if(IFFUNC_ISNAKED(sym->type)) {
3467 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3472 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3474 pic16_emitcode ("mov","%s,_bp",spname);
3478 /* if use external stack but some variables were
3479 added to the local stack then decrement the
3481 if (options.useXstack && sym->stack) {
3482 pic16_emitcode("mov","a,sp");
3483 pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3484 pic16_emitcode("mov","sp,a");
3489 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3490 if (options.useXstack) {
3491 pic16_emitcode("mov","r0,%s",spname);
3492 pic16_emitcode("movx","a,@r0");
3493 pic16_emitcode("mov","_bp,a");
3494 pic16_emitcode("dec","%s",spname);
3498 pic16_emitcode ("pop","_bp");
3503 if (IFFUNC_ISISR(sym->type)) {
3504 /* now we need to restore the registers */
3505 /* if any registers used */
3506 if (sym->regsUsed) {
3509 /* restore registers used */
3510 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3511 for ( i = sym->regsUsed->size; i >= 0; i--) {
3512 if (bitVectBitValue(sym->regsUsed,i)) {
3514 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3515 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3516 // pic16_regWithIdx(i)->name);
3518 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3520 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3521 // &pic16_pc_preinc1,
3522 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3528 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3529 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3530 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3531 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3533 if(!(_G.interruptvector == 1)) {
3534 /* do not restore interrupt vector for WREG,STATUS,BSR
3535 * for high priority interrupt, see genFunction */
3537 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3538 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3539 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3542 _G.interruptvector = 0; /* sanity check */
3544 // pic16_pBlockConvert2ISR(pb);
3547 /* if debug then send end of function */
3548 /* if (options.debug && currFunc) */
3550 debugFile->writeEndFunction (currFunc, ic, 1);
3553 pic16_emitpcodeNULLop(POC_RETFIE);
3555 if (IFFUNC_ISCRITICAL(sym->type))
3556 pic16_emitcode("setb","ea");
3559 // pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3561 /* if any registers used */
3562 if (sym->regsUsed) {
3564 /* save the registers used */
3565 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3566 for ( i = sym->regsUsed->size; i >= 0; i--) {
3567 if (bitVectBitValue(sym->regsUsed,i)) {
3569 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3570 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3571 // pic16_regWithIdx(i)->name);
3573 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3575 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3576 // &pic16_pc_preinc1,
3577 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3584 pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3585 /* if debug then send end of function */
3587 debugFile->writeEndFunction (currFunc, ic, 1);
3590 /* insert code to restore stack frame, if user enabled it
3591 * and function is not main() */
3594 if(strcmp(sym->name, "main")) {
3595 if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3596 /* restore stack frame */
3597 if(STACK_MODEL_LARGE)
3598 pic16_emitpcode(POC_MOVFF,
3599 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3600 pic16_emitpcode(POC_MOVFF,
3601 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3605 pic16_emitcode ("return","");
3606 pic16_emitpcodeNULLop(POC_RETURN);
3608 /* Mark the end of a function */
3609 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3615 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3619 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3621 if(dest->type != PO_WREG)
3622 pic16_emitpcode(POC_MOVWF, dest);
3624 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3625 pic16_popGet(AOP(op), offset), dest));
3629 /*-----------------------------------------------------------------*/
3630 /* genRet - generate code for return statement */
3631 /*-----------------------------------------------------------------*/
3632 static void genRet (iCode *ic)
3637 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3638 /* if we have no return value then
3639 * just generate the "ret" */
3644 /* we have something to return then
3645 * move the return value into place */
3646 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3647 size = AOP_SIZE(IC_LEFT(ic));
3651 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3652 // pic16_emitpcode(POC_MOVFF,
3653 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3656 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3657 // pic16_emitpcode(POC_MOVFF,
3658 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3661 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3662 // pic16_emitpcode(POC_MOVFF,
3663 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3666 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3668 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3669 // pic16_emitpcode(POC_MOVFF,
3670 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3673 /* >32-bits, setup stack and FSR0 */
3675 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3676 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3678 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3680 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3685 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3686 pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3688 if(STACK_MODEL_LARGE) {
3689 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3690 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3692 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3697 /* old code, left here for reference -- VR */
3701 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3703 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3704 pic16_emitpcomment("push %s",l);
3707 DEBUGpic16_emitcode(";", "%d", __LINE__);
3708 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3709 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3711 if (strcmp(fReturn[offset],l)) {
3712 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3713 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3714 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3716 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3720 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3730 if (strcmp(fReturn[pushed],"a"))
3731 pic16_emitcode("pop",fReturn[pushed]);
3733 pic16_emitcode("pop","acc");
3739 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3742 /* generate a jump to the return label
3743 * if the next is not the return statement */
3744 if (!(ic->next && ic->next->op == LABEL
3745 && IC_LABEL(ic->next) == returnLabel)) {
3747 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3748 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3752 /*-----------------------------------------------------------------*/
3753 /* genLabel - generates a label */
3754 /*-----------------------------------------------------------------*/
3755 static void genLabel (iCode *ic)
3759 /* special case never generate */
3760 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3761 if (IC_LABEL(ic) == entryLabel)
3764 pic16_emitpLabel(IC_LABEL(ic)->key);
3765 pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3768 /*-----------------------------------------------------------------*/
3769 /* genGoto - generates a goto */
3770 /*-----------------------------------------------------------------*/
3772 static void genGoto (iCode *ic)
3774 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3775 pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3779 /*-----------------------------------------------------------------*/
3780 /* genMultbits :- multiplication of bits */
3781 /*-----------------------------------------------------------------*/
3782 static void genMultbits (operand *left,
3786 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3788 if(!pic16_sameRegs(AOP(result),AOP(right)))
3789 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3791 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3792 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3793 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3798 /*-----------------------------------------------------------------*/
3799 /* genMultOneByte : 8 bit multiplication & division */
3800 /*-----------------------------------------------------------------*/
3801 static void genMultOneByte (operand *left,
3806 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3807 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3808 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3810 /* (if two literals, the value is computed before) */
3811 /* if one literal, literal on the right */
3812 if (AOP_TYPE(left) == AOP_LIT){
3818 /* size is already checked in genMult == 1 */
3819 // size = AOP_SIZE(result);
3821 if (AOP_TYPE(right) == AOP_LIT){
3822 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3823 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3824 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3825 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3827 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3828 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3829 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3830 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3833 pic16_genMult8X8_8 (left, right,result);
3836 /*-----------------------------------------------------------------*/
3837 /* genMultOneWord : 16 bit multiplication */
3838 /*-----------------------------------------------------------------*/
3839 static void genMultOneWord (operand *left,
3844 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3845 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3846 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3848 /* (if two literals, the value is computed before)
3849 * if one literal, literal on the right */
3850 if (AOP_TYPE(left) == AOP_LIT){
3856 /* size is checked already == 2 */
3857 // size = AOP_SIZE(result);
3859 if (AOP_TYPE(right) == AOP_LIT) {
3860 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3861 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3862 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3863 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3865 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3866 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3867 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3868 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3871 pic16_genMult16X16_16(left, right,result);
3874 /*-----------------------------------------------------------------*/
3875 /* genMultOneLong : 32 bit multiplication */
3876 /*-----------------------------------------------------------------*/
3877 static void genMultOneLong (operand *left,
3882 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3883 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3884 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3886 /* (if two literals, the value is computed before)
3887 * if one literal, literal on the right */
3888 if (AOP_TYPE(left) == AOP_LIT){
3894 /* size is checked already == 4 */
3895 // size = AOP_SIZE(result);
3897 if (AOP_TYPE(right) == AOP_LIT) {
3898 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3899 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3900 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3901 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3903 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3904 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3905 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3906 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3909 pic16_genMult32X32_32(left, right,result);
3914 /*-----------------------------------------------------------------*/
3915 /* genMult - generates code for multiplication */
3916 /*-----------------------------------------------------------------*/
3917 static void genMult (iCode *ic)
3919 operand *left = IC_LEFT(ic);
3920 operand *right = IC_RIGHT(ic);
3921 operand *result= IC_RESULT(ic);
3923 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3924 /* assign the amsops */
3925 pic16_aopOp (left,ic,FALSE);
3926 pic16_aopOp (right,ic,FALSE);
3927 pic16_aopOp (result,ic,TRUE);
3929 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3931 /* special cases first *
3933 if (AOP_TYPE(left) == AOP_CRY
3934 && AOP_TYPE(right)== AOP_CRY) {
3935 genMultbits(left,right,result);
3939 /* if both are of size == 1 */
3940 if(AOP_SIZE(left) == 1
3941 && AOP_SIZE(right) == 1) {
3942 genMultOneByte(left,right,result);
3946 /* if both are of size == 2 */
3947 if(AOP_SIZE(left) == 2
3948 && AOP_SIZE(right) == 2) {
3949 genMultOneWord(left, right, result);
3953 /* if both are of size == 4 */
3954 if(AOP_SIZE(left) == 4
3955 && AOP_SIZE(right) == 4) {
3956 genMultOneLong(left, right, result);
3960 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3963 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3964 /* should have been converted to function call */
3968 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3969 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3970 pic16_freeAsmop(result,NULL,ic,TRUE);
3973 /*-----------------------------------------------------------------*/
3974 /* genDivbits :- division of bits */
3975 /*-----------------------------------------------------------------*/
3976 static void genDivbits (operand *left,
3983 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3984 /* the result must be bit */
3985 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3986 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3990 pic16_emitcode("div","ab");
3991 pic16_emitcode("rrc","a");
3992 pic16_aopPut(AOP(result),"c",0);
3995 /*-----------------------------------------------------------------*/
3996 /* genDivOneByte : 8 bit division */
3997 /*-----------------------------------------------------------------*/
3998 static void genDivOneByte (operand *left,
4002 sym_link *opetype = operandType(result);
4007 /* result = divident / divisor
4008 * - divident may be a register or a literal,
4009 * - divisor may be a register or a literal,
4010 * so there are 3 cases (literal / literal is optimized
4011 * by the front-end) to handle.
4012 * In addition we must handle signed and unsigned, which
4013 * result in 6 final different cases -- VR */
4015 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4016 size = AOP_SIZE(result) - 1;
4018 /* signed or unsigned */
4019 if (SPEC_USIGN(opetype)) {
4020 pCodeOp *pct1, /* count */
4023 symbol *label1, *label2, *label3;;
4026 /* unsigned is easy */
4028 pct1 = pic16_popGetTempReg();
4029 pct2 = pic16_popGetTempReg();
4030 pct3 = pic16_popGetTempReg();
4032 label1 = newiTempLabel(NULL);
4033 label2 = newiTempLabel(NULL);
4034 label3 = newiTempLabel(NULL);
4036 /* the following algorithm is extracted from divuint.c */
4038 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4039 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4041 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4043 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4045 pic16_emitpLabel(label1->key);
4048 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4052 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4056 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4058 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4059 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4061 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4062 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4063 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4065 pic16_emitpLabel( label3->key );
4066 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4067 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4071 pic16_emitpLabel(label2->key);
4072 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4073 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4074 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4076 /* result is in wreg */
4077 if(AOP_TYPE(result) != AOP_ACC)
4078 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4080 pic16_popReleaseTempReg( pct3 );
4081 pic16_popReleaseTempReg( pct2 );
4082 pic16_popReleaseTempReg( pct1 );
4087 /* signed is a little bit more difficult */
4089 /* save the signs of the operands */
4090 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4092 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4093 pic16_emitcode("push","acc"); /* save it on the stack */
4095 /* now sign adjust for both left & right */
4096 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4098 lbl = newiTempLabel(NULL);
4099 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4100 pic16_emitcode("cpl","a");
4101 pic16_emitcode("inc","a");
4102 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4103 pic16_emitcode("mov","b,a");
4105 /* sign adjust left side */
4106 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4109 lbl = newiTempLabel(NULL);
4110 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4111 pic16_emitcode("cpl","a");
4112 pic16_emitcode("inc","a");
4113 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4115 /* now the division */
4116 pic16_emitcode("div","ab");
4117 /* we are interested in the lower order
4119 pic16_emitcode("mov","b,a");
4120 lbl = newiTempLabel(NULL);
4121 pic16_emitcode("pop","acc");
4122 /* if there was an over flow we don't
4123 adjust the sign of the result */
4124 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4125 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4127 pic16_emitcode("clr","a");
4128 pic16_emitcode("subb","a,b");
4129 pic16_emitcode("mov","b,a");
4130 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4132 /* now we are done */
4133 pic16_aopPut(AOP(result),"b",0);
4135 pic16_emitcode("mov","c,b.7");
4136 pic16_emitcode("subb","a,acc");
4139 pic16_aopPut(AOP(result),"a",offset++);
4143 /*-----------------------------------------------------------------*/
4144 /* genDiv - generates code for division */
4145 /*-----------------------------------------------------------------*/
4146 static void genDiv (iCode *ic)
4148 operand *left = IC_LEFT(ic);
4149 operand *right = IC_RIGHT(ic);
4150 operand *result= IC_RESULT(ic);
4153 /* Division is a very lengthy algorithm, so it is better
4154 * to call support routines than inlining algorithm.
4155 * Division functions written here just in case someone
4156 * wants to inline and not use the support libraries -- VR */
4158 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4159 /* assign the amsops */
4160 pic16_aopOp (left,ic,FALSE);
4161 pic16_aopOp (right,ic,FALSE);
4162 pic16_aopOp (result,ic,TRUE);
4164 /* special cases first */
4166 if (AOP_TYPE(left) == AOP_CRY &&
4167 AOP_TYPE(right)== AOP_CRY) {
4168 genDivbits(left,right,result);
4172 /* if both are of size == 1 */
4173 if (AOP_SIZE(left) == 1 &&
4174 AOP_SIZE(right) == 1 ) {
4175 genDivOneByte(left,right,result);
4179 /* should have been converted to function call */
4182 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4183 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4184 pic16_freeAsmop(result,NULL,ic,TRUE);
4187 /*-----------------------------------------------------------------*/
4188 /* genModbits :- modulus of bits */
4189 /*-----------------------------------------------------------------*/
4190 static void genModbits (operand *left,
4197 /* the result must be bit */
4198 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4199 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4203 pic16_emitcode("div","ab");
4204 pic16_emitcode("mov","a,b");
4205 pic16_emitcode("rrc","a");
4206 pic16_aopPut(AOP(result),"c",0);
4209 /*-----------------------------------------------------------------*/
4210 /* genModOneByte : 8 bit modulus */
4211 /*-----------------------------------------------------------------*/
4212 static void genModOneByte (operand *left,
4216 sym_link *opetype = operandType(result);
4220 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4221 /* signed or unsigned */
4222 if (SPEC_USIGN(opetype)) {
4223 /* unsigned is easy */
4224 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4225 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4227 pic16_emitcode("div","ab");
4228 pic16_aopPut(AOP(result),"b",0);
4232 /* signed is a little bit more difficult */
4234 /* save the signs of the operands */
4235 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4238 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4239 pic16_emitcode("push","acc"); /* save it on the stack */
4241 /* now sign adjust for both left & right */
4242 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4245 lbl = newiTempLabel(NULL);
4246 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4247 pic16_emitcode("cpl","a");
4248 pic16_emitcode("inc","a");
4249 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4250 pic16_emitcode("mov","b,a");
4252 /* sign adjust left side */
4253 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4256 lbl = newiTempLabel(NULL);
4257 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4258 pic16_emitcode("cpl","a");
4259 pic16_emitcode("inc","a");
4260 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4262 /* now the multiplication */
4263 pic16_emitcode("div","ab");
4264 /* we are interested in the lower order
4266 lbl = newiTempLabel(NULL);
4267 pic16_emitcode("pop","acc");
4268 /* if there was an over flow we don't
4269 adjust the sign of the result */
4270 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4271 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4273 pic16_emitcode("clr","a");
4274 pic16_emitcode("subb","a,b");
4275 pic16_emitcode("mov","b,a");
4276 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4278 /* now we are done */
4279 pic16_aopPut(AOP(result),"b",0);
4283 /*-----------------------------------------------------------------*/
4284 /* genMod - generates code for division */
4285 /*-----------------------------------------------------------------*/
4286 static void genMod (iCode *ic)
4288 operand *left = IC_LEFT(ic);
4289 operand *right = IC_RIGHT(ic);
4290 operand *result= IC_RESULT(ic);
4292 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4293 /* assign the amsops */
4294 pic16_aopOp (left,ic,FALSE);
4295 pic16_aopOp (right,ic,FALSE);
4296 pic16_aopOp (result,ic,TRUE);
4298 /* special cases first */
4300 if (AOP_TYPE(left) == AOP_CRY &&
4301 AOP_TYPE(right)== AOP_CRY) {
4302 genModbits(left,right,result);
4306 /* if both are of size == 1 */
4307 if (AOP_SIZE(left) == 1 &&
4308 AOP_SIZE(right) == 1 ) {
4309 genModOneByte(left,right,result);
4313 /* should have been converted to function call */
4317 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4318 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4319 pic16_freeAsmop(result,NULL,ic,TRUE);
4322 /*-----------------------------------------------------------------*/
4323 /* genIfxJump :- will create a jump depending on the ifx */
4324 /*-----------------------------------------------------------------*/
4326 note: May need to add parameter to indicate when a variable is in bit space.
4328 static void genIfxJump (iCode *ic, char *jval)
4331 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4332 /* if true label then we jump if condition
4334 if ( IC_TRUE(ic) ) {
4336 if(strcmp(jval,"a") == 0)
4338 else if (strcmp(jval,"c") == 0)
4341 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4342 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1));
4345 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4346 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4350 /* false label is present */
4351 if(strcmp(jval,"a") == 0)
4353 else if (strcmp(jval,"c") == 0)
4356 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4357 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1));
4360 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4361 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4366 /* mark the icode as generated */
4373 /*-----------------------------------------------------------------*/
4375 /*-----------------------------------------------------------------*/
4376 static void genSkip(iCode *ifx,int status_bit)
4378 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4382 if ( IC_TRUE(ifx) ) {
4383 switch(status_bit) {
4398 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4399 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4403 switch(status_bit) {
4417 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4418 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4425 /*-----------------------------------------------------------------*/
4427 /*-----------------------------------------------------------------*/
4428 static void genSkipc(resolvedIfx *rifx)
4430 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4440 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4441 rifx->generated = 1;
4444 /*-----------------------------------------------------------------*/
4446 /*-----------------------------------------------------------------*/
4447 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4449 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4454 if( (rifx->condition ^ invert_condition) & 1)
4459 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4460 rifx->generated = 1;
4464 /*-----------------------------------------------------------------*/
4466 /*-----------------------------------------------------------------*/
4467 static void genSkipz(iCode *ifx, int condition)
4478 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4480 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4483 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4485 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4490 /*-----------------------------------------------------------------*/
4492 /*-----------------------------------------------------------------*/
4493 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4499 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4501 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4504 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4505 rifx->generated = 1;
4509 /*-----------------------------------------------------------------*/
4510 /* genChkZeroes :- greater or less than comparison */
4511 /* For each byte in a literal that is zero, inclusive or the */
4512 /* the corresponding byte in the operand with W */
4513 /* returns true if any of the bytes are zero */
4514 /*-----------------------------------------------------------------*/
4515 static int genChkZeroes(operand *op, int lit, int size)
4522 i = (lit >> (size*8)) & 0xff;
4526 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4528 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4537 /*-----------------------------------------------------------------*/
4538 /* genCmp :- greater or less than comparison */
4539 /*-----------------------------------------------------------------*/
4540 static void genCmp (operand *left,operand *right,
4541 operand *result, iCode *ifx, int sign)
4543 int size; //, offset = 0 ;
4544 unsigned long lit = 0L,i = 0;
4545 resolvedIfx rFalseIfx;
4546 // resolvedIfx rTrueIfx;
4548 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4551 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4552 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4556 resolveIfx(&rFalseIfx,ifx);
4557 truelbl = newiTempLabel(NULL);
4558 size = max(AOP_SIZE(left),AOP_SIZE(right));
4560 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4564 /* if literal is on the right then swap with left */
4565 if ((AOP_TYPE(right) == AOP_LIT)) {
4566 operand *tmp = right ;
4567 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4568 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4571 lit = (lit - 1) & mask;
4574 rFalseIfx.condition ^= 1;
4577 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4578 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4582 //if(IC_TRUE(ifx) == NULL)
4583 /* if left & right are bit variables */
4584 if (AOP_TYPE(left) == AOP_CRY &&
4585 AOP_TYPE(right) == AOP_CRY ) {
4586 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4587 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4589 /* subtract right from left if at the
4590 end the carry flag is set then we know that
4591 left is greater than right */
4593 symbol *lbl = newiTempLabel(NULL);
4596 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4597 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+labelOffset, lbl->key+100+labelOffset);
4601 if(AOP_TYPE(right) == AOP_LIT) {
4603 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4605 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4612 genSkipCond(&rFalseIfx,left,size-1,7);
4614 /* no need to compare to 0...*/
4615 /* NOTE: this is a de-generate compare that most certainly
4616 * creates some dead code. */
4617 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4619 if(ifx) ifx->generated = 1;
4626 //i = (lit >> (size*8)) & 0xff;
4627 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4629 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4631 i = ((0-lit) & 0xff);
4634 /* lit is 0x7f, all signed chars are less than
4635 * this except for 0x7f itself */
4636 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4637 genSkipz2(&rFalseIfx,0);
4639 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4640 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4641 genSkipc(&rFalseIfx);
4646 genSkipz2(&rFalseIfx,1);
4648 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4649 genSkipc(&rFalseIfx);
4653 if(ifx) ifx->generated = 1;
4657 /* chars are out of the way. now do ints and longs */
4660 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4667 genSkipCond(&rFalseIfx,left,size,7);
4668 if(ifx) ifx->generated = 1;
4673 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4675 //rFalseIfx.condition ^= 1;
4676 //genSkipCond(&rFalseIfx,left,size,7);
4677 //rFalseIfx.condition ^= 1;
4679 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4680 if(rFalseIfx.condition)
4681 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4683 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4685 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4686 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4687 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4690 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4692 if(rFalseIfx.condition) {
4694 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4700 genSkipc(&rFalseIfx);
4701 pic16_emitpLabel(truelbl->key);
4702 if(ifx) ifx->generated = 1;
4709 if( (lit & 0xff) == 0) {
4710 /* lower byte is zero */
4711 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4712 i = ((lit >> 8) & 0xff) ^0x80;
4713 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4714 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4715 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4716 genSkipc(&rFalseIfx);
4719 if(ifx) ifx->generated = 1;
4724 /* Special cases for signed longs */
4725 if( (lit & 0xffffff) == 0) {
4726 /* lower byte is zero */
4727 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4728 i = ((lit >> 8*3) & 0xff) ^0x80;
4729 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4730 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4731 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4732 genSkipc(&rFalseIfx);
4735 if(ifx) ifx->generated = 1;
4743 if(lit & (0x80 << (size*8))) {
4744 /* lit is negative */
4745 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4747 //genSkipCond(&rFalseIfx,left,size,7);
4749 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4751 if(rFalseIfx.condition)
4752 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4754 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4758 /* lit is positive */
4759 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4760 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4761 if(rFalseIfx.condition)
4762 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4764 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4769 This works, but is only good for ints.
4770 It also requires a "known zero" register.
4771 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4772 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4773 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
4774 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4775 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4776 genSkipc(&rFalseIfx);
4778 pic16_emitpLabel(truelbl->key);
4779 if(ifx) ifx->generated = 1;
4783 /* There are no more special cases, so perform a general compare */
4785 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4786 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4790 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4792 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4794 //rFalseIfx.condition ^= 1;
4795 genSkipc(&rFalseIfx);
4797 pic16_emitpLabel(truelbl->key);
4799 if(ifx) ifx->generated = 1;
4806 /* sign is out of the way. So now do an unsigned compare */
4807 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4810 /* General case - compare to an unsigned literal on the right.*/
4812 i = (lit >> (size*8)) & 0xff;
4813 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4814 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4816 i = (lit >> (size*8)) & 0xff;
4819 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4821 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4823 /* this byte of the lit is zero,
4824 *if it's not the last then OR in the variable */
4826 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4831 pic16_emitpLabel(lbl->key);
4832 // pic16_emitpLabel(truelbl->key);
4833 //if(emitFinalCheck)
4834 genSkipc(&rFalseIfx);
4836 pic16_emitpLabel(truelbl->key);
4838 if(ifx) ifx->generated = 1;
4845 if(AOP_TYPE(left) == AOP_LIT) {
4846 //symbol *lbl = newiTempLabel(NULL);
4848 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4851 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4854 if((lit == 0) && (sign == 0)){
4857 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4859 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4861 genSkipz2(&rFalseIfx,0);
4862 if(ifx) ifx->generated = 1;
4869 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4870 /* degenerate compare can never be true */
4871 if(rFalseIfx.condition == 0)
4872 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4874 if(ifx) ifx->generated = 1;
4879 /* signed comparisons to a literal byte */
4881 int lp1 = (lit+1) & 0xff;
4883 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4886 rFalseIfx.condition ^= 1;
4887 genSkipCond(&rFalseIfx,right,0,7);
4890 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4891 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4892 genSkipz2(&rFalseIfx,1);
4895 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4896 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4897 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4898 rFalseIfx.condition ^= 1;
4899 genSkipc(&rFalseIfx);
4903 /* unsigned comparisons to a literal byte */
4905 switch(lit & 0xff ) {
4907 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4908 genSkipz2(&rFalseIfx,0);
4911 rFalseIfx.condition ^= 1;
4912 genSkipCond(&rFalseIfx,right,0,7);
4916 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4917 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4918 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4919 rFalseIfx.condition ^= 1;
4920 if (AOP_TYPE(result) == AOP_CRY)
4921 genSkipc(&rFalseIfx);
4923 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4924 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4930 if(ifx) ifx->generated = 1;
4931 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
4937 /* Size is greater than 1 */
4945 /* this means lit = 0xffffffff, or -1 */
4948 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4949 rFalseIfx.condition ^= 1;
4950 genSkipCond(&rFalseIfx,right,size,7);
4951 if(ifx) ifx->generated = 1;
4958 if(rFalseIfx.condition) {
4959 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4960 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4963 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4965 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4969 if(rFalseIfx.condition) {
4970 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4971 pic16_emitpLabel(truelbl->key);
4973 rFalseIfx.condition ^= 1;
4974 genSkipCond(&rFalseIfx,right,s,7);
4977 if(ifx) ifx->generated = 1;
4981 if((size == 1) && (0 == (lp1&0xff))) {
4982 /* lower byte of signed word is zero */
4983 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4984 i = ((lp1 >> 8) & 0xff) ^0x80;
4985 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4986 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4987 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4988 rFalseIfx.condition ^= 1;
4989 genSkipc(&rFalseIfx);
4992 if(ifx) ifx->generated = 1;
4996 if(lit & (0x80 << (size*8))) {
4997 /* Lit is less than zero */
4998 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4999 //rFalseIfx.condition ^= 1;
5000 //genSkipCond(&rFalseIfx,left,size,7);
5001 //rFalseIfx.condition ^= 1;
5002 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5003 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5005 if(rFalseIfx.condition)
5006 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5008 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5012 /* Lit is greater than or equal to zero */
5013 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5014 //rFalseIfx.condition ^= 1;
5015 //genSkipCond(&rFalseIfx,right,size,7);
5016 //rFalseIfx.condition ^= 1;
5018 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5019 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5021 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5022 if(rFalseIfx.condition)
5023 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5025 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5030 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5031 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5035 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5037 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5039 rFalseIfx.condition ^= 1;
5040 //rFalseIfx.condition = 1;
5041 genSkipc(&rFalseIfx);
5043 pic16_emitpLabel(truelbl->key);
5045 if(ifx) ifx->generated = 1;
5050 /* compare word or long to an unsigned literal on the right.*/
5055 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5058 break; /* handled above */
5061 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5063 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5064 genSkipz2(&rFalseIfx,0);
5068 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5070 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5073 if(rFalseIfx.condition)
5074 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5076 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5079 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5080 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5082 rFalseIfx.condition ^= 1;
5083 genSkipc(&rFalseIfx);
5086 pic16_emitpLabel(truelbl->key);
5088 if(ifx) ifx->generated = 1;
5094 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5095 i = (lit >> (size*8)) & 0xff;
5097 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5098 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5101 i = (lit >> (size*8)) & 0xff;
5104 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5106 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5108 /* this byte of the lit is zero,
5109 * if it's not the last then OR in the variable */
5111 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5116 pic16_emitpLabel(lbl->key);
5118 rFalseIfx.condition ^= 1;
5120 genSkipc(&rFalseIfx);
5124 pic16_emitpLabel(truelbl->key);
5125 if(ifx) ifx->generated = 1;
5129 /* Compare two variables */
5131 DEBUGpic16_emitcode(";sign","%d",sign);
5135 /* Sigh. thus sucks... */
5137 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5138 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5139 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5140 pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5141 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5142 pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5144 /* Signed char comparison */
5145 /* Special thanks to Nikolai Golovchenko for this snippet */
5146 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5147 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5148 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5149 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5150 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5151 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5153 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5154 genSkipc(&rFalseIfx);
5156 if(ifx) ifx->generated = 1;
5162 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5163 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5167 /* The rest of the bytes of a multi-byte compare */
5171 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5174 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5175 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5180 pic16_emitpLabel(lbl->key);
5182 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5183 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5184 (AOP_TYPE(result) == AOP_REG)) {
5185 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5186 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5188 genSkipc(&rFalseIfx);
5190 //genSkipc(&rFalseIfx);
5191 if(ifx) ifx->generated = 1;
5198 if ((AOP_TYPE(result) != AOP_CRY)
5199 && AOP_SIZE(result)) {
5200 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5201 // pic16_emitpLabel( rFalseIfx.lbl->key );
5203 pic16_outBitC(result);
5205 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5206 /* if the result is used in the next
5207 ifx conditional branch then generate
5208 code a little differently */
5210 genIfxJump (ifx,"c");
5212 pic16_outBitC(result);
5213 /* leave the result in acc */
5218 /*-----------------------------------------------------------------*/
5219 /* genCmpGt :- greater than comparison */
5220 /*-----------------------------------------------------------------*/
5221 static void genCmpGt (iCode *ic, iCode *ifx)
5223 operand *left, *right, *result;
5224 sym_link *letype , *retype;
5227 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5229 right= IC_RIGHT(ic);
5230 result = IC_RESULT(ic);
5232 letype = getSpec(operandType(left));
5233 retype =getSpec(operandType(right));
5234 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5235 /* assign the amsops */
5236 pic16_aopOp (left,ic,FALSE);
5237 pic16_aopOp (right,ic,FALSE);
5238 pic16_aopOp (result,ic,TRUE);
5240 genCmp(right, left, result, ifx, sign);
5242 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5243 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5244 pic16_freeAsmop(result,NULL,ic,TRUE);
5247 /*-----------------------------------------------------------------*/
5248 /* genCmpLt - less than comparisons */
5249 /*-----------------------------------------------------------------*/
5250 static void genCmpLt (iCode *ic, iCode *ifx)
5252 operand *left, *right, *result;
5253 sym_link *letype , *retype;
5256 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5258 right= IC_RIGHT(ic);
5259 result = IC_RESULT(ic);
5261 letype = getSpec(operandType(left));
5262 retype =getSpec(operandType(right));
5263 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5265 /* assign the amsops */
5266 pic16_aopOp (left,ic,FALSE);
5267 pic16_aopOp (right,ic,FALSE);
5268 pic16_aopOp (result,ic,TRUE);
5270 genCmp(left, right, result, ifx, sign);
5272 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5273 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5274 pic16_freeAsmop(result,NULL,ic,TRUE);
5279 // FIXME reenable literal optimisation when the pic16 port is stable
5281 /*-----------------------------------------------------------------*/
5282 /* genc16bit2lit - compare a 16 bit value to a literal */
5283 /*-----------------------------------------------------------------*/
5284 static void genc16bit2lit(operand *op, int lit, int offset)
5288 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
5289 if( (lit&0xff) == 0)
5294 switch( BYTEofLONG(lit,i)) {
5296 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5299 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5302 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5305 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5306 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5311 switch( BYTEofLONG(lit,i)) {
5313 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5317 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5321 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5324 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5326 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5335 /*-----------------------------------------------------------------*/
5336 /* gencjneshort - compare and jump if not equal */
5337 /*-----------------------------------------------------------------*/
5338 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5340 int size = max(AOP_SIZE(left),AOP_SIZE(right));
5342 int res_offset = 0; /* the result may be a different size then left or right */
5343 int res_size = AOP_SIZE(result);
5345 symbol *lbl, *lbl_done;
5347 unsigned long lit = 0L;
5348 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5350 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5351 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5353 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
5354 resolveIfx(&rIfx,ifx);
5355 lbl = newiTempLabel(NULL);
5356 lbl_done = newiTempLabel(NULL);
5359 /* if the left side is a literal or
5360 if the right is in a pointer register and left
5362 if ((AOP_TYPE(left) == AOP_LIT) ||
5363 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5368 if(AOP_TYPE(right) == AOP_LIT)
5369 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5371 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5372 preserve_result = 1;
5374 if(result && !preserve_result)
5377 for(i = 0; i < AOP_SIZE(result); i++)
5378 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5382 /* if the right side is a literal then anything goes */
5383 if (AOP_TYPE(right) == AOP_LIT &&
5384 AOP_TYPE(left) != AOP_DIR ) {
5387 genc16bit2lit(left, lit, 0);
5389 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5392 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5395 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5396 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5398 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5402 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5404 if(res_offset < res_size-1)
5412 /* if the right side is in a register or in direct space or
5413 if the left is a pointer register & right is not */
5414 else if (AOP_TYPE(right) == AOP_REG ||
5415 AOP_TYPE(right) == AOP_DIR ||
5416 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5417 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5418 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5419 int lbl_key = lbl->key;
5422 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5423 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5425 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5426 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5427 __FUNCTION__,__LINE__);
5431 /* switch(size) { */
5433 /* genc16bit2lit(left, lit, 0); */
5435 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5440 if((AOP_TYPE(left) == AOP_DIR) &&
5441 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5443 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5444 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5446 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5448 switch (lit & 0xff) {
5450 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5453 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5454 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5455 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5459 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5460 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5461 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5462 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5466 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5467 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5472 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5475 if(AOP_TYPE(result) == AOP_CRY) {
5476 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5481 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5483 /* fix me. probably need to check result size too */
5484 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5489 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5490 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5497 if(res_offset < res_size-1)
5502 } else if(AOP_TYPE(right) == AOP_REG &&
5503 AOP_TYPE(left) != AOP_DIR){
5506 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5507 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5508 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5513 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5515 if(res_offset < res_size-1)
5520 /* right is a pointer reg need both a & b */
5522 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5524 pic16_emitcode("mov","b,%s",l);
5525 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5526 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5531 if(result && preserve_result)
5534 for(i = 0; i < AOP_SIZE(result); i++)
5535 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5538 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5540 if(result && preserve_result)
5541 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5544 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5546 pic16_emitpLabel(lbl->key);
5548 if(result && preserve_result)
5551 for(i = 0; i < AOP_SIZE(result); i++)
5552 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5554 pic16_emitpLabel(lbl_done->key);
5557 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5565 /*-----------------------------------------------------------------*/
5566 /* gencjne - compare and jump if not equal */
5567 /*-----------------------------------------------------------------*/
5568 static void gencjne(operand *left, operand *right, iCode *ifx)
5570 symbol *tlbl = newiTempLabel(NULL);
5572 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5573 gencjneshort(left, right, lbl);
5575 pic16_emitcode("mov","a,%s",one);
5576 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5577 pic16_emitcode("","%05d_DS_:",lbl->key+100);
5578 pic16_emitcode("clr","a");
5579 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5581 pic16_emitpLabel(lbl->key);
5582 pic16_emitpLabel(tlbl->key);
5588 /*-----------------------------------------------------------------*/
5589 /* is_LitOp - check if operand has to be treated as literal */
5590 /*-----------------------------------------------------------------*/
5591 static bool is_LitOp(operand *op)
5593 return (AOP_TYPE(op) == AOP_LIT)
5594 || ( (AOP_TYPE(op) == AOP_PCODE)
5595 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5596 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));
5599 /*-----------------------------------------------------------------*/
5600 /* is_LitAOp - check if operand has to be treated as literal */
5601 /*-----------------------------------------------------------------*/
5602 static bool is_LitAOp(asmop *aop)
5604 return (aop->type == AOP_LIT)
5605 || ( (aop->type == AOP_PCODE)
5606 && ( (aop->aopu.pcop->type == PO_LITERAL)
5607 || (aop->aopu.pcop->type == PO_IMMEDIATE) ));
5612 /*-----------------------------------------------------------------*/
5613 /* genCmpEq - generates code for equal to */
5614 /*-----------------------------------------------------------------*/
5615 static void genCmpEq (iCode *ic, iCode *ifx)
5617 operand *left, *right, *result;
5618 symbol *falselbl = newiTempLabel(NULL);
5619 symbol *donelbl = newiTempLabel(NULL);
5621 int preserve_result = 0;
5622 int generate_result = 0;
5625 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5626 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5627 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5629 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5630 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5632 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5634 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5635 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5639 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5641 operand *tmp = right ;
5646 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5647 preserve_result = 1;
5649 if(result && AOP_SIZE(result))
5650 generate_result = 1;
5652 if(generate_result && !preserve_result)
5654 for(i = 0; i < AOP_SIZE(result); i++)
5655 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5658 for(i=0; i < AOP_SIZE(left); i++)
5660 if(AOP_TYPE(left) != AOP_ACC)
5663 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5665 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5668 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
5670 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
5672 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5677 if(generate_result && preserve_result)
5679 for(i = 0; i < AOP_SIZE(result); i++)
5680 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5684 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5686 if(generate_result && preserve_result)
5687 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5689 if(ifx && IC_TRUE(ifx))
5690 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5692 if(ifx && IC_FALSE(ifx))
5693 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5695 pic16_emitpLabel(falselbl->key);
5699 if(ifx && IC_FALSE(ifx))
5700 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5702 if(generate_result && preserve_result)
5704 for(i = 0; i < AOP_SIZE(result); i++)
5705 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5708 pic16_emitpLabel(donelbl->key);
5714 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5715 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5716 pic16_freeAsmop(result,NULL,ic,TRUE);
5722 // old version kept for reference
5724 /*-----------------------------------------------------------------*/
5725 /* genCmpEq - generates code for equal to */
5726 /*-----------------------------------------------------------------*/
5727 static void genCmpEq (iCode *ic, iCode *ifx)
5729 operand *left, *right, *result;
5730 unsigned long lit = 0L;
5732 symbol *falselbl = newiTempLabel(NULL);
5735 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5738 DEBUGpic16_emitcode ("; ifx is non-null","");
5740 DEBUGpic16_emitcode ("; ifx is null","");
5742 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5743 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5744 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5746 size = max(AOP_SIZE(left),AOP_SIZE(right));
5748 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5750 /* if literal, literal on the right or
5751 if the right is in a pointer register and left
5753 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
5754 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5755 operand *tmp = right ;
5761 if(ifx && !AOP_SIZE(result)){
5763 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
5764 /* if they are both bit variables */
5765 if (AOP_TYPE(left) == AOP_CRY &&
5766 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5767 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
5768 if(AOP_TYPE(right) == AOP_LIT){
5769 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5771 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5772 pic16_emitcode("cpl","c");
5773 } else if(lit == 1L) {
5774 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5776 pic16_emitcode("clr","c");
5778 /* AOP_TYPE(right) == AOP_CRY */
5780 symbol *lbl = newiTempLabel(NULL);
5781 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5782 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5783 pic16_emitcode("cpl","c");
5784 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5786 /* if true label then we jump if condition
5788 tlbl = newiTempLabel(NULL);
5789 if ( IC_TRUE(ifx) ) {
5790 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5791 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5793 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5794 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5796 pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5799 /* left and right are both bit variables, result is carry */
5802 resolveIfx(&rIfx,ifx);
5804 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5805 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5806 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5807 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5812 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
5814 /* They're not both bit variables. Is the right a literal? */
5815 if(AOP_TYPE(right) == AOP_LIT) {
5816 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5821 switch(lit & 0xff) {
5823 if ( IC_TRUE(ifx) ) {
5824 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5826 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5828 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5829 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5833 if ( IC_TRUE(ifx) ) {
5834 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5836 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5838 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5839 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5843 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5845 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5850 /* end of size == 1 */
5854 genc16bit2lit(left,lit,offset);
5857 /* end of size == 2 */
5862 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5863 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5864 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5865 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5868 /* search for patterns that can be optimized */
5870 genc16bit2lit(left,lit,0);
5874 emitSKPZ; // if hi word unequal
5876 emitSKPNZ; // if hi word equal
5878 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5879 genc16bit2lit(left,lit,2);
5882 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5883 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5887 pic16_emitpLabel(falselbl->key);
5896 } else if(AOP_TYPE(right) == AOP_CRY ) {
5897 /* we know the left is not a bit, but that the right is */
5898 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5899 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5900 pic16_popGet(AOP(right),offset));
5901 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5903 /* if the two are equal, then W will be 0 and the Z bit is set
5904 * we could test Z now, or go ahead and check the high order bytes if
5905 * the variable we're comparing is larger than a byte. */
5908 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5910 if ( IC_TRUE(ifx) ) {
5912 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5913 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5916 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5917 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5921 /* They're both variables that are larger than bits */
5924 tlbl = newiTempLabel(NULL);
5927 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5928 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5930 if ( IC_TRUE(ifx) ) {
5934 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5936 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5937 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5941 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5944 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5945 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5950 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5952 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5953 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5957 if(s>1 && IC_TRUE(ifx)) {
5958 pic16_emitpLabel(tlbl->key);
5959 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
5963 /* mark the icode as generated */
5968 /* if they are both bit variables */
5969 if (AOP_TYPE(left) == AOP_CRY &&
5970 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5971 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
5972 if(AOP_TYPE(right) == AOP_LIT){
5973 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5975 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5976 pic16_emitcode("cpl","c");
5977 } else if(lit == 1L) {
5978 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5980 pic16_emitcode("clr","c");
5982 /* AOP_TYPE(right) == AOP_CRY */
5984 symbol *lbl = newiTempLabel(NULL);
5985 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5986 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5987 pic16_emitcode("cpl","c");
5988 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5991 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5992 pic16_outBitC(result);
5996 genIfxJump (ifx,"c");
5999 /* if the result is used in an arithmetic operation
6000 then put the result in place */
6001 pic16_outBitC(result);
6004 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
6005 gencjne(left,right,result,ifx);
6008 gencjne(left,right,newiTempLabel(NULL));
6010 if(IC_TRUE(ifx)->key)
6011 gencjne(left,right,IC_TRUE(ifx)->key);
6013 gencjne(left,right,IC_FALSE(ifx)->key);
6017 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6018 pic16_aopPut(AOP(result),"a",0);
6023 genIfxJump (ifx,"a");
6027 /* if the result is used in an arithmetic operation
6028 then put the result in place */
6030 if (AOP_TYPE(result) != AOP_CRY)
6031 pic16_outAcc(result);
6033 /* leave the result in acc */
6037 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6038 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6039 pic16_freeAsmop(result,NULL,ic,TRUE);
6043 /*-----------------------------------------------------------------*/
6044 /* ifxForOp - returns the icode containing the ifx for operand */
6045 /*-----------------------------------------------------------------*/
6046 static iCode *ifxForOp ( operand *op, iCode *ic )
6048 /* if true symbol then needs to be assigned */
6049 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6050 if (IS_TRUE_SYMOP(op))
6053 /* if this has register type condition and
6054 the next instruction is ifx with the same operand
6055 and live to of the operand is upto the ifx only then */
6057 && ic->next->op == IFX
6058 && IC_COND(ic->next)->key == op->key
6059 && OP_SYMBOL(op)->liveTo <= ic->next->seq
6061 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6066 ic->next->op == IFX &&
6067 IC_COND(ic->next)->key == op->key) {
6068 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6072 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6074 ic->next->op == IFX)
6075 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6078 ic->next->op == IFX &&
6079 IC_COND(ic->next)->key == op->key) {
6080 DEBUGpic16_emitcode ("; "," key is okay");
6081 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6082 OP_SYMBOL(op)->liveTo,
6087 /* the code below is completely untested
6088 * it just allows ulong2fs.c compile -- VR */
6091 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6092 __FILE__, __FUNCTION__, __LINE__);
6094 /* if this has register type condition and
6095 the next instruction is ifx with the same operand
6096 and live to of the operand is upto the ifx only then */
6098 ic->next->op == IFX &&
6099 IC_COND(ic->next)->key == op->key &&
6100 OP_SYMBOL(op)->liveTo <= ic->next->seq )
6104 ic->next->op == IFX &&
6105 IC_COND(ic->next)->key == op->key) {
6106 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6110 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6111 __FILE__, __FUNCTION__, __LINE__);
6113 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
6118 /*-----------------------------------------------------------------*/
6119 /* genAndOp - for && operation */
6120 /*-----------------------------------------------------------------*/
6121 static void genAndOp (iCode *ic)
6123 operand *left,*right, *result;
6126 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6127 /* note here that && operations that are in an
6128 if statement are taken away by backPatchLabels
6129 only those used in arthmetic operations remain */
6130 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6131 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6132 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6134 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6136 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6137 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6138 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6140 /* if both are bit variables */
6141 /* if (AOP_TYPE(left) == AOP_CRY && */
6142 /* AOP_TYPE(right) == AOP_CRY ) { */
6143 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6144 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6145 /* pic16_outBitC(result); */
6147 /* tlbl = newiTempLabel(NULL); */
6148 /* pic16_toBoolean(left); */
6149 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6150 /* pic16_toBoolean(right); */
6151 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6152 /* pic16_outBitAcc(result); */
6155 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6156 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6157 pic16_freeAsmop(result,NULL,ic,TRUE);
6161 /*-----------------------------------------------------------------*/
6162 /* genOrOp - for || operation */
6163 /*-----------------------------------------------------------------*/
6166 modified this code, but it doesn't appear to ever get called
6169 static void genOrOp (iCode *ic)
6171 operand *left,*right, *result;
6174 /* note here that || operations that are in an
6175 if statement are taken away by backPatchLabels
6176 only those used in arthmetic operations remain */
6177 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6178 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6179 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6180 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6182 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6184 /* if both are bit variables */
6185 if (AOP_TYPE(left) == AOP_CRY &&
6186 AOP_TYPE(right) == AOP_CRY ) {
6187 pic16_emitcode("clrc","");
6188 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6189 AOP(left)->aopu.aop_dir,
6190 AOP(left)->aopu.aop_dir);
6191 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6192 AOP(right)->aopu.aop_dir,
6193 AOP(right)->aopu.aop_dir);
6194 pic16_emitcode("setc","");
6197 tlbl = newiTempLabel(NULL);
6198 pic16_toBoolean(left);
6200 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
6201 pic16_toBoolean(right);
6202 pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
6204 pic16_outBitAcc(result);
6207 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6208 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6209 pic16_freeAsmop(result,NULL,ic,TRUE);
6212 /*-----------------------------------------------------------------*/
6213 /* isLiteralBit - test if lit == 2^n */
6214 /*-----------------------------------------------------------------*/
6215 static int isLiteralBit(unsigned long lit)
6217 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6218 0x100L,0x200L,0x400L,0x800L,
6219 0x1000L,0x2000L,0x4000L,0x8000L,
6220 0x10000L,0x20000L,0x40000L,0x80000L,
6221 0x100000L,0x200000L,0x400000L,0x800000L,
6222 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6223 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6226 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6227 for(idx = 0; idx < 32; idx++)
6233 /*-----------------------------------------------------------------*/
6234 /* continueIfTrue - */
6235 /*-----------------------------------------------------------------*/
6236 static void continueIfTrue (iCode *ic)
6238 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6240 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6244 /*-----------------------------------------------------------------*/
6246 /*-----------------------------------------------------------------*/
6247 static void jumpIfTrue (iCode *ic)
6249 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6251 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6255 /*-----------------------------------------------------------------*/
6256 /* jmpTrueOrFalse - */
6257 /*-----------------------------------------------------------------*/
6258 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6260 // ugly but optimized by peephole
6261 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6263 symbol *nlbl = newiTempLabel(NULL);
6264 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
6265 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6266 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6267 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6270 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6271 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6276 /*-----------------------------------------------------------------*/
6277 /* genAnd - code for and */
6278 /*-----------------------------------------------------------------*/
6279 static void genAnd (iCode *ic, iCode *ifx)
6281 operand *left, *right, *result;
6283 unsigned long lit = 0L;
6288 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6289 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6290 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6291 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6293 resolveIfx(&rIfx,ifx);
6295 /* if left is a literal & right is not then exchange them */
6296 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6297 AOP_NEEDSACC(left)) {
6298 operand *tmp = right ;
6303 /* if result = right then exchange them */
6304 if(pic16_sameRegs(AOP(result),AOP(right))){
6305 operand *tmp = right ;
6310 /* if right is bit then exchange them */
6311 if (AOP_TYPE(right) == AOP_CRY &&
6312 AOP_TYPE(left) != AOP_CRY){
6313 operand *tmp = right ;
6317 if(AOP_TYPE(right) == AOP_LIT)
6318 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6320 size = AOP_SIZE(result);
6322 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6325 // result = bit & yy;
6326 if (AOP_TYPE(left) == AOP_CRY){
6327 // c = bit & literal;
6328 if(AOP_TYPE(right) == AOP_LIT){
6330 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6333 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6336 if(size && (AOP_TYPE(result) == AOP_CRY)){
6337 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6340 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6344 pic16_emitcode("clr","c");
6347 if (AOP_TYPE(right) == AOP_CRY){
6349 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6350 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6353 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6355 pic16_emitcode("rrc","a");
6356 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6362 pic16_outBitC(result);
6364 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6365 genIfxJump(ifx, "c");
6369 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6370 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6371 if((AOP_TYPE(right) == AOP_LIT) &&
6372 (AOP_TYPE(result) == AOP_CRY) &&
6373 (AOP_TYPE(left) != AOP_CRY)){
6374 int posbit = isLiteralBit(lit);
6378 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6381 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6387 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6388 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6390 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6391 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6394 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6395 size = AOP_SIZE(left);
6398 int bp = posbit, ofs=0;
6405 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6406 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0));
6410 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6411 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6413 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6420 symbol *tlbl = newiTempLabel(NULL);
6421 int sizel = AOP_SIZE(left);
6423 pic16_emitcode("setb","c");
6425 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6426 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6428 if((posbit = isLiteralBit(bytelit)) != 0)
6429 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6431 if(bytelit != 0x0FFL)
6432 pic16_emitcode("anl","a,%s",
6433 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6434 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6439 // bit = left & literal
6441 pic16_emitcode("clr","c");
6442 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6444 // if(left & literal)
6447 jmpTrueOrFalse(ifx, tlbl);
6451 pic16_outBitC(result);
6455 /* if left is same as result */
6456 if(pic16_sameRegs(AOP(result),AOP(left))){
6458 for(;size--; offset++,lit>>=8) {
6459 if(AOP_TYPE(right) == AOP_LIT){
6460 switch(lit & 0xff) {
6462 /* and'ing with 0 has clears the result */
6463 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6464 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6467 /* and'ing with 0xff is a nop when the result and left are the same */
6472 int p = my_powof2( (~lit) & 0xff );
6474 /* only one bit is set in the literal, so use a bcf instruction */
6475 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6476 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6479 pic16_emitcode("movlw","0x%x", (lit & 0xff));
6480 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6481 if(know_W != (lit&0xff))
6482 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6484 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6489 if (AOP_TYPE(left) == AOP_ACC) {
6490 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6492 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6493 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6500 // left & result in different registers
6501 if(AOP_TYPE(result) == AOP_CRY){
6503 // if(size), result in bit
6504 // if(!size && ifx), conditional oper: if(left & right)
6505 symbol *tlbl = newiTempLabel(NULL);
6506 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6508 pic16_emitcode("setb","c");
6510 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6511 pic16_emitcode("anl","a,%s",
6512 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6513 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6518 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6519 pic16_outBitC(result);
6521 jmpTrueOrFalse(ifx, tlbl);
6523 for(;(size--);offset++) {
6525 // result = left & right
6526 if(AOP_TYPE(right) == AOP_LIT){
6527 int t = (lit >> (offset*8)) & 0x0FFL;
6530 pic16_emitcode("clrf","%s",
6531 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6532 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6535 pic16_emitcode("movf","%s,w",
6536 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6537 pic16_emitcode("movwf","%s",
6538 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6539 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6540 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6543 pic16_emitcode("movlw","0x%x",t);
6544 pic16_emitcode("andwf","%s,w",
6545 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6546 pic16_emitcode("movwf","%s",
6547 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6549 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6550 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6551 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6556 if (AOP_TYPE(left) == AOP_ACC) {
6557 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6558 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6560 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6561 pic16_emitcode("andwf","%s,w",
6562 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6563 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6564 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6566 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6567 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6573 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6574 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6575 pic16_freeAsmop(result,NULL,ic,TRUE);
6578 /*-----------------------------------------------------------------*/
6579 /* genOr - code for or */
6580 /*-----------------------------------------------------------------*/
6581 static void genOr (iCode *ic, iCode *ifx)
6583 operand *left, *right, *result;
6585 unsigned long lit = 0L;
6587 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6589 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6590 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6591 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6593 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6595 /* if left is a literal & right is not then exchange them */
6596 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6597 AOP_NEEDSACC(left)) {
6598 operand *tmp = right ;
6603 /* if result = right then exchange them */
6604 if(pic16_sameRegs(AOP(result),AOP(right))){
6605 operand *tmp = right ;
6610 /* if right is bit then exchange them */
6611 if (AOP_TYPE(right) == AOP_CRY &&
6612 AOP_TYPE(left) != AOP_CRY){
6613 operand *tmp = right ;
6618 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6620 if(AOP_TYPE(right) == AOP_LIT)
6621 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6623 size = AOP_SIZE(result);
6627 if (AOP_TYPE(left) == AOP_CRY){
6628 if(AOP_TYPE(right) == AOP_LIT){
6629 // c = bit & literal;
6631 // lit != 0 => result = 1
6632 if(AOP_TYPE(result) == AOP_CRY){
6634 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6635 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6636 // AOP(result)->aopu.aop_dir,
6637 // AOP(result)->aopu.aop_dir);
6639 continueIfTrue(ifx);
6643 // lit == 0 => result = left
6644 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6646 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6649 if (AOP_TYPE(right) == AOP_CRY){
6650 if(pic16_sameRegs(AOP(result),AOP(left))){
6652 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6653 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6654 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6656 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6657 AOP(result)->aopu.aop_dir,
6658 AOP(result)->aopu.aop_dir);
6659 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6660 AOP(right)->aopu.aop_dir,
6661 AOP(right)->aopu.aop_dir);
6662 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6663 AOP(result)->aopu.aop_dir,
6664 AOP(result)->aopu.aop_dir);
6666 if( AOP_TYPE(result) == AOP_ACC) {
6667 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6668 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6669 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6670 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6674 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6675 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6676 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6677 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6679 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6680 AOP(result)->aopu.aop_dir,
6681 AOP(result)->aopu.aop_dir);
6682 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6683 AOP(right)->aopu.aop_dir,
6684 AOP(right)->aopu.aop_dir);
6685 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6686 AOP(left)->aopu.aop_dir,
6687 AOP(left)->aopu.aop_dir);
6688 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6689 AOP(result)->aopu.aop_dir,
6690 AOP(result)->aopu.aop_dir);
6695 symbol *tlbl = newiTempLabel(NULL);
6696 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6699 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6700 if( AOP_TYPE(right) == AOP_ACC) {
6701 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6703 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6704 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6709 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6710 pic16_emitcode(";XXX setb","c");
6711 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6712 AOP(left)->aopu.aop_dir,tlbl->key+100);
6713 pic16_toBoolean(right);
6714 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6715 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6716 jmpTrueOrFalse(ifx, tlbl);
6720 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6727 pic16_outBitC(result);
6729 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6730 genIfxJump(ifx, "c");
6734 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6735 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6736 if((AOP_TYPE(right) == AOP_LIT) &&
6737 (AOP_TYPE(result) == AOP_CRY) &&
6738 (AOP_TYPE(left) != AOP_CRY)){
6740 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6743 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6745 continueIfTrue(ifx);
6748 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6749 // lit = 0, result = boolean(left)
6751 pic16_emitcode(";XXX setb","c");
6752 pic16_toBoolean(right);
6754 symbol *tlbl = newiTempLabel(NULL);
6755 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6757 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6759 genIfxJump (ifx,"a");
6763 pic16_outBitC(result);
6767 /* if left is same as result */
6768 if(pic16_sameRegs(AOP(result),AOP(left))){
6770 for(;size--; offset++,lit>>=8) {
6771 if(AOP_TYPE(right) == AOP_LIT){
6772 if((lit & 0xff) == 0)
6773 /* or'ing with 0 has no effect */
6776 int p = my_powof2(lit & 0xff);
6778 /* only one bit is set in the literal, so use a bsf instruction */
6779 pic16_emitpcode(POC_BSF,
6780 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6782 if(know_W != (lit & 0xff))
6783 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6784 know_W = lit & 0xff;
6785 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6790 if (AOP_TYPE(left) == AOP_ACC) {
6791 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
6792 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6794 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6795 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6797 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6798 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6804 // left & result in different registers
6805 if(AOP_TYPE(result) == AOP_CRY){
6807 // if(size), result in bit
6808 // if(!size && ifx), conditional oper: if(left | right)
6809 symbol *tlbl = newiTempLabel(NULL);
6810 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6811 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6815 pic16_emitcode(";XXX setb","c");
6817 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6818 pic16_emitcode(";XXX orl","a,%s",
6819 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6820 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6825 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6826 pic16_outBitC(result);
6828 jmpTrueOrFalse(ifx, tlbl);
6829 } else for(;(size--);offset++){
6831 // result = left & right
6832 if(AOP_TYPE(right) == AOP_LIT){
6833 int t = (lit >> (offset*8)) & 0x0FFL;
6836 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
6837 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6839 pic16_emitcode("movf","%s,w",
6840 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6841 pic16_emitcode("movwf","%s",
6842 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6845 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6846 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6847 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6849 pic16_emitcode("movlw","0x%x",t);
6850 pic16_emitcode("iorwf","%s,w",
6851 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6852 pic16_emitcode("movwf","%s",
6853 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6859 // faster than result <- left, anl result,right
6860 // and better if result is SFR
6861 if (AOP_TYPE(left) == AOP_ACC) {
6862 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
6863 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6865 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6866 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6868 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6869 pic16_emitcode("iorwf","%s,w",
6870 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6872 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6873 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6878 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6879 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6880 pic16_freeAsmop(result,NULL,ic,TRUE);
6883 /*-----------------------------------------------------------------*/
6884 /* genXor - code for xclusive or */
6885 /*-----------------------------------------------------------------*/
6886 static void genXor (iCode *ic, iCode *ifx)
6888 operand *left, *right, *result;
6890 unsigned long lit = 0L;
6892 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6894 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6895 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6896 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6898 /* if left is a literal & right is not ||
6899 if left needs acc & right does not */
6900 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6901 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6902 operand *tmp = right ;
6907 /* if result = right then exchange them */
6908 if(pic16_sameRegs(AOP(result),AOP(right))){
6909 operand *tmp = right ;
6914 /* if right is bit then exchange them */
6915 if (AOP_TYPE(right) == AOP_CRY &&
6916 AOP_TYPE(left) != AOP_CRY){
6917 operand *tmp = right ;
6921 if(AOP_TYPE(right) == AOP_LIT)
6922 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6924 size = AOP_SIZE(result);
6928 if (AOP_TYPE(left) == AOP_CRY){
6929 if(AOP_TYPE(right) == AOP_LIT){
6930 // c = bit & literal;
6932 // lit>>1 != 0 => result = 1
6933 if(AOP_TYPE(result) == AOP_CRY){
6935 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
6936 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6938 continueIfTrue(ifx);
6941 pic16_emitcode("setb","c");
6945 // lit == 0, result = left
6946 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6948 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6950 // lit == 1, result = not(left)
6951 if(size && pic16_sameRegs(AOP(result),AOP(left))){
6952 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
6953 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
6954 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6957 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6958 pic16_emitcode("cpl","c");
6965 symbol *tlbl = newiTempLabel(NULL);
6966 if (AOP_TYPE(right) == AOP_CRY){
6968 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6971 int sizer = AOP_SIZE(right);
6973 // if val>>1 != 0, result = 1
6974 pic16_emitcode("setb","c");
6976 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6978 // test the msb of the lsb
6979 pic16_emitcode("anl","a,#0xfe");
6980 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6984 pic16_emitcode("rrc","a");
6986 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6987 pic16_emitcode("cpl","c");
6988 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6993 pic16_outBitC(result);
6995 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6996 genIfxJump(ifx, "c");
7000 if(pic16_sameRegs(AOP(result),AOP(left))){
7001 /* if left is same as result */
7002 for(;size--; offset++) {
7003 if(AOP_TYPE(right) == AOP_LIT){
7004 int t = (lit >> (offset*8)) & 0x0FFL;
7008 if (IS_AOP_PREG(left)) {
7009 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7010 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7011 pic16_aopPut(AOP(result),"a",offset);
7013 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7014 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7015 pic16_emitcode("xrl","%s,%s",
7016 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7017 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7020 if (AOP_TYPE(left) == AOP_ACC)
7021 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7023 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7024 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7026 if (IS_AOP_PREG(left)) {
7027 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7028 pic16_aopPut(AOP(result),"a",offset);
7030 pic16_emitcode("xrl","%s,a",
7031 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7037 // left & result in different registers
7038 if(AOP_TYPE(result) == AOP_CRY){
7040 // if(size), result in bit
7041 // if(!size && ifx), conditional oper: if(left ^ right)
7042 symbol *tlbl = newiTempLabel(NULL);
7043 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7045 pic16_emitcode("setb","c");
7047 if((AOP_TYPE(right) == AOP_LIT) &&
7048 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7049 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7051 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7052 pic16_emitcode("xrl","a,%s",
7053 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7055 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7060 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7061 pic16_outBitC(result);
7063 jmpTrueOrFalse(ifx, tlbl);
7064 } else for(;(size--);offset++){
7066 // result = left & right
7067 if(AOP_TYPE(right) == AOP_LIT){
7068 int t = (lit >> (offset*8)) & 0x0FFL;
7071 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7072 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7073 pic16_emitcode("movf","%s,w",
7074 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7075 pic16_emitcode("movwf","%s",
7076 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7079 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7080 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7081 pic16_emitcode("comf","%s,w",
7082 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7083 pic16_emitcode("movwf","%s",
7084 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7087 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7088 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7089 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7090 pic16_emitcode("movlw","0x%x",t);
7091 pic16_emitcode("xorwf","%s,w",
7092 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7093 pic16_emitcode("movwf","%s",
7094 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7100 // faster than result <- left, anl result,right
7101 // and better if result is SFR
7102 if (AOP_TYPE(left) == AOP_ACC) {
7103 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7104 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7106 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7107 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7108 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7109 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7111 if ( AOP_TYPE(result) != AOP_ACC){
7112 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7113 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7119 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7120 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7121 pic16_freeAsmop(result,NULL,ic,TRUE);
7124 /*-----------------------------------------------------------------*/
7125 /* genInline - write the inline code out */
7126 /*-----------------------------------------------------------------*/
7127 static void genInline (iCode *ic)
7129 char *buffer, *bp, *bp1;
7131 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7133 _G.inLine += (!options.asmpeep);
7135 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7136 strcpy(buffer,IC_INLINE(ic));
7138 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7140 /* emit each line as a code */
7146 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7154 /* print label, use this special format with NULL directive
7155 * to denote that the argument should not be indented with tab */
7156 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7163 if ((bp1 != bp) && *bp1)
7164 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7169 _G.inLine -= (!options.asmpeep);
7172 /*-----------------------------------------------------------------*/
7173 /* genRRC - rotate right with carry */
7174 /*-----------------------------------------------------------------*/
7175 static void genRRC (iCode *ic)
7177 operand *left , *result ;
7178 int size, offset = 0, same;
7180 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7182 /* rotate right with carry */
7184 result=IC_RESULT(ic);
7185 pic16_aopOp (left,ic,FALSE);
7186 pic16_aopOp (result,ic,FALSE);
7188 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7190 same = pic16_sameRegs(AOP(result),AOP(left));
7192 size = AOP_SIZE(result);
7194 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7196 /* get the lsb and put it into the carry */
7197 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7204 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7206 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7207 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7213 pic16_freeAsmop(left,NULL,ic,TRUE);
7214 pic16_freeAsmop(result,NULL,ic,TRUE);
7217 /*-----------------------------------------------------------------*/
7218 /* genRLC - generate code for rotate left with carry */
7219 /*-----------------------------------------------------------------*/
7220 static void genRLC (iCode *ic)
7222 operand *left , *result ;
7223 int size, offset = 0;
7226 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7227 /* rotate right with carry */
7229 result=IC_RESULT(ic);
7230 pic16_aopOp (left,ic,FALSE);
7231 pic16_aopOp (result,ic,FALSE);
7233 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7235 same = pic16_sameRegs(AOP(result),AOP(left));
7237 /* move it to the result */
7238 size = AOP_SIZE(result);
7240 /* get the msb and put it into the carry */
7241 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7248 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7250 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7251 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7258 pic16_freeAsmop(left,NULL,ic,TRUE);
7259 pic16_freeAsmop(result,NULL,ic,TRUE);
7263 /* gpasm can get the highest order bit with HIGH/UPPER
7264 * so the following probably is not needed -- VR */
7266 /*-----------------------------------------------------------------*/
7267 /* genGetHbit - generates code get highest order bit */
7268 /*-----------------------------------------------------------------*/
7269 static void genGetHbit (iCode *ic)
7271 operand *left, *result;
7273 result=IC_RESULT(ic);
7274 pic16_aopOp (left,ic,FALSE);
7275 pic16_aopOp (result,ic,FALSE);
7277 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7278 /* get the highest order byte into a */
7279 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7280 if(AOP_TYPE(result) == AOP_CRY){
7281 pic16_emitcode("rlc","a");
7282 pic16_outBitC(result);
7285 pic16_emitcode("rl","a");
7286 pic16_emitcode("anl","a,#0x01");
7287 pic16_outAcc(result);
7291 pic16_freeAsmop(left,NULL,ic,TRUE);
7292 pic16_freeAsmop(result,NULL,ic,TRUE);
7296 /*-----------------------------------------------------------------*/
7297 /* AccRol - rotate left accumulator by known count */
7298 /*-----------------------------------------------------------------*/
7299 static void AccRol (int shCount)
7301 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7302 shCount &= 0x0007; // shCount : 0..7
7307 pic16_emitcode("rl","a");
7310 pic16_emitcode("rl","a");
7311 pic16_emitcode("rl","a");
7314 pic16_emitcode("swap","a");
7315 pic16_emitcode("rr","a");
7318 pic16_emitcode("swap","a");
7321 pic16_emitcode("swap","a");
7322 pic16_emitcode("rl","a");
7325 pic16_emitcode("rr","a");
7326 pic16_emitcode("rr","a");
7329 pic16_emitcode("rr","a");
7335 /*-----------------------------------------------------------------*/
7336 /* AccLsh - left shift accumulator by known count */
7337 /*-----------------------------------------------------------------*/
7338 static void AccLsh (int shCount)
7340 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7346 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7349 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7350 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7353 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7354 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7357 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7360 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7361 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7364 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7365 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7368 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7372 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7375 /*-----------------------------------------------------------------*/
7376 /* AccRsh - right shift accumulator by known count */
7377 /*-----------------------------------------------------------------*/
7378 static void AccRsh (int shCount, int andmask)
7380 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7385 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7386 // andmask = 0; /* no need */
7389 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7390 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7391 // andmask = 0; /* no need */
7394 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7395 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7398 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7401 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7402 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7405 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7406 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7409 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7414 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7416 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7420 /*-----------------------------------------------------------------*/
7421 /* AccSRsh - signed right shift accumulator by known count */
7422 /*-----------------------------------------------------------------*/
7423 static void AccSRsh (int shCount)
7426 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7429 pic16_emitcode("mov","c,acc.7");
7430 pic16_emitcode("rrc","a");
7431 } else if(shCount == 2){
7432 pic16_emitcode("mov","c,acc.7");
7433 pic16_emitcode("rrc","a");
7434 pic16_emitcode("mov","c,acc.7");
7435 pic16_emitcode("rrc","a");
7437 tlbl = newiTempLabel(NULL);
7438 /* rotate right accumulator */
7439 AccRol(8 - shCount);
7440 /* and kill the higher order bits */
7441 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7442 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7443 pic16_emitcode("orl","a,#0x%02x",
7444 (unsigned char)~SRMask[shCount]);
7445 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7450 /*-----------------------------------------------------------------*/
7451 /* shiftR1Left2Result - shift right one byte from left to result */
7452 /*-----------------------------------------------------------------*/
7453 static void shiftR1Left2ResultSigned (operand *left, int offl,
7454 operand *result, int offr,
7459 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7461 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7465 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7467 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7469 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7470 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7476 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7478 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7480 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7481 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7483 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7484 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7490 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7492 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7493 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7496 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7497 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7498 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7500 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7501 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7503 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7507 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7508 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7509 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7510 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
7511 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7515 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7517 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7518 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7520 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7521 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
7522 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7523 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
7524 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7529 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7530 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7531 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7532 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7533 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7534 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7536 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7537 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7538 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7539 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7540 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7546 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7547 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7548 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7549 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7551 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7552 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7553 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7561 /*-----------------------------------------------------------------*/
7562 /* shiftR1Left2Result - shift right one byte from left to result */
7563 /*-----------------------------------------------------------------*/
7564 static void shiftR1Left2Result (operand *left, int offl,
7565 operand *result, int offr,
7566 int shCount, int sign)
7570 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7572 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7574 /* Copy the msb into the carry if signed. */
7576 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7586 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7588 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7589 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7595 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7597 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7598 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7601 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7606 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7608 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7609 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7612 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7613 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7614 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7615 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7619 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7620 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7621 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7625 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7626 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7627 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7629 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7634 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7635 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7636 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7637 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7638 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7643 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7644 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7645 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7654 /*-----------------------------------------------------------------*/
7655 /* shiftL1Left2Result - shift left one byte from left to result */
7656 /*-----------------------------------------------------------------*/
7657 static void shiftL1Left2Result (operand *left, int offl,
7658 operand *result, int offr, int shCount)
7663 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7665 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7666 DEBUGpic16_emitcode ("; ***","same = %d",same);
7667 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7669 /* shift left accumulator */
7670 //AccLsh(shCount); // don't comment out just yet...
7671 // pic16_aopPut(AOP(result),"a",offr);
7675 /* Shift left 1 bit position */
7676 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7678 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7680 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7681 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7685 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7686 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7687 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7688 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7691 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7692 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7693 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7694 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7695 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7698 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7699 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7700 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7703 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7704 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7705 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7706 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7709 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7710 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7711 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7712 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7713 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7716 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7717 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7718 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7722 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7727 /*-----------------------------------------------------------------*/
7728 /* movLeft2Result - move byte from left to result */
7729 /*-----------------------------------------------------------------*/
7730 static void movLeft2Result (operand *left, int offl,
7731 operand *result, int offr)
7734 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7735 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7736 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7738 if (*l == '@' && (IS_AOP_PREG(result))) {
7739 pic16_emitcode("mov","a,%s",l);
7740 pic16_aopPut(AOP(result),"a",offr);
7742 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7743 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7748 /*-----------------------------------------------------------------*/
7749 /* shiftL2Left2Result - shift left two bytes from left to result */
7750 /*-----------------------------------------------------------------*/
7751 static void shiftL2Left2Result (operand *left, int offl,
7752 operand *result, int offr, int shCount)
7754 int same = pic16_sameRegs(AOP(result), AOP(left));
7757 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7759 if (same && (offl != offr)) { // shift bytes
7762 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7763 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7765 } else { // just treat as different later on
7778 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7779 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7780 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7784 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7785 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7791 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7792 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7793 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7794 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7795 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7796 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7797 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7799 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7800 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7804 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7805 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7806 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7807 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7808 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7809 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7810 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7811 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7812 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7813 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7816 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7817 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7818 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7819 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7820 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7830 /* note, use a mov/add for the shift since the mov has a
7831 chance of getting optimized out */
7832 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7833 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7834 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7835 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7836 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7840 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7841 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7847 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7848 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7849 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7850 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7851 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7852 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7853 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7854 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7858 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7859 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7863 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7864 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7865 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7866 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7868 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7869 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7870 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7871 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7872 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7873 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7874 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7875 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7878 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7879 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7880 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7881 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7882 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7887 /*-----------------------------------------------------------------*/
7888 /* shiftR2Left2Result - shift right two bytes from left to result */
7889 /*-----------------------------------------------------------------*/
7890 static void shiftR2Left2Result (operand *left, int offl,
7891 operand *result, int offr,
7892 int shCount, int sign)
7894 int same = pic16_sameRegs(AOP(result), AOP(left));
7896 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7898 if (same && (offl != offr)) { // shift right bytes
7901 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7902 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7904 } else { // just treat as different later on
7916 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7921 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7922 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7924 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7925 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7926 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7927 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7932 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7935 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7936 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7943 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7944 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7945 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7947 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7948 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7949 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7950 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7952 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7953 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7954 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7956 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7957 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7958 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7959 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7960 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7964 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7965 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7969 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7970 pic16_emitpcode(POC_BTFSC,
7971 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7972 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7980 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7981 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7983 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7984 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7985 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7986 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7988 pic16_emitpcode(POC_BTFSC,
7989 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7990 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7992 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7993 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7994 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7995 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7997 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7998 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7999 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8000 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8001 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8002 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8003 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8004 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8006 pic16_emitpcode(POC_BTFSC,
8007 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
8008 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8010 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8011 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8018 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8019 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8020 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8021 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8024 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8026 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8031 /*-----------------------------------------------------------------*/
8032 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8033 /*-----------------------------------------------------------------*/
8034 static void shiftLLeftOrResult (operand *left, int offl,
8035 operand *result, int offr, int shCount)
8037 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8039 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8040 /* shift left accumulator */
8042 /* or with result */
8043 /* back to result */
8044 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8047 /*-----------------------------------------------------------------*/
8048 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8049 /*-----------------------------------------------------------------*/
8050 static void shiftRLeftOrResult (operand *left, int offl,
8051 operand *result, int offr, int shCount)
8053 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8055 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8056 /* shift right accumulator */
8058 /* or with result */
8059 /* back to result */
8060 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8063 /*-----------------------------------------------------------------*/
8064 /* genlshOne - left shift a one byte quantity by known count */
8065 /*-----------------------------------------------------------------*/
8066 static void genlshOne (operand *result, operand *left, int shCount)
8068 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8069 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8072 /*-----------------------------------------------------------------*/
8073 /* genlshTwo - left shift two bytes by known amount != 0 */
8074 /*-----------------------------------------------------------------*/
8075 static void genlshTwo (operand *result,operand *left, int shCount)
8079 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8080 size = pic16_getDataSize(result);
8082 /* if shCount >= 8 */
8088 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8090 movLeft2Result(left, LSB, result, MSB16);
8092 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8095 /* 1 <= shCount <= 7 */
8098 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8100 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8104 /*-----------------------------------------------------------------*/
8105 /* shiftLLong - shift left one long from left to result */
8106 /* offr = LSB or MSB16 */
8107 /*-----------------------------------------------------------------*/
8108 static void shiftLLong (operand *left, operand *result, int offr )
8110 int size = AOP_SIZE(result);
8111 int same = pic16_sameRegs(AOP(left),AOP(result));
8114 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8116 if (same && (offr == MSB16)) { //shift one byte
8117 for(i=size-1;i>=MSB16;i--) {
8118 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8119 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8122 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8125 if (size >= LSB+offr ){
8127 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8129 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8130 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8134 if(size >= MSB16+offr){
8136 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8138 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8139 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8143 if(size >= MSB24+offr){
8145 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8147 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8148 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8152 if(size > MSB32+offr){
8154 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8156 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8157 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8161 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8165 /*-----------------------------------------------------------------*/
8166 /* genlshFour - shift four byte by a known amount != 0 */
8167 /*-----------------------------------------------------------------*/
8168 static void genlshFour (operand *result, operand *left, int shCount)
8172 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8173 size = AOP_SIZE(result);
8175 /* if shifting more that 3 bytes */
8176 if (shCount >= 24 ) {
8179 /* lowest order of left goes to the highest
8180 order of the destination */
8181 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8183 movLeft2Result(left, LSB, result, MSB32);
8185 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8186 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8187 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8192 /* more than two bytes */
8193 else if ( shCount >= 16 ) {
8194 /* lower order two bytes goes to higher order two bytes */
8196 /* if some more remaining */
8198 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8200 movLeft2Result(left, MSB16, result, MSB32);
8201 movLeft2Result(left, LSB, result, MSB24);
8203 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8204 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8208 /* if more than 1 byte */
8209 else if ( shCount >= 8 ) {
8210 /* lower order three bytes goes to higher order three bytes */
8214 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8216 movLeft2Result(left, LSB, result, MSB16);
8218 else{ /* size = 4 */
8220 movLeft2Result(left, MSB24, result, MSB32);
8221 movLeft2Result(left, MSB16, result, MSB24);
8222 movLeft2Result(left, LSB, result, MSB16);
8223 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8225 else if(shCount == 1)
8226 shiftLLong(left, result, MSB16);
8228 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8229 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8230 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8231 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8236 /* 1 <= shCount <= 7 */
8237 else if(shCount <= 3)
8239 shiftLLong(left, result, LSB);
8240 while(--shCount >= 1)
8241 shiftLLong(result, result, LSB);
8243 /* 3 <= shCount <= 7, optimize */
8245 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8246 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8247 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8251 /*-----------------------------------------------------------------*/
8252 /* genLeftShiftLiteral - left shifting by known count */
8253 /*-----------------------------------------------------------------*/
8254 static void genLeftShiftLiteral (operand *left,
8259 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8262 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8263 pic16_freeAsmop(right,NULL,ic,TRUE);
8265 pic16_aopOp(left,ic,FALSE);
8266 pic16_aopOp(result,ic,FALSE);
8268 size = getSize(operandType(result));
8271 pic16_emitcode("; shift left ","result %d, left %d",size,
8275 /* I suppose that the left size >= result size */
8278 movLeft2Result(left, size, result, size);
8282 else if(shCount >= (size * 8))
8284 pic16_aopPut(AOP(result),zero,size);
8288 genlshOne (result,left,shCount);
8293 genlshTwo (result,left,shCount);
8297 genlshFour (result,left,shCount);
8301 pic16_freeAsmop(left,NULL,ic,TRUE);
8302 pic16_freeAsmop(result,NULL,ic,TRUE);
8305 /*-----------------------------------------------------------------*
8306 * genMultiAsm - repeat assembly instruction for size of register.
8307 * if endian == 1, then the high byte (i.e base address + size of
8308 * register) is used first else the low byte is used first;
8309 *-----------------------------------------------------------------*/
8310 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8315 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8328 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
8333 /*-----------------------------------------------------------------*/
8334 /* genLeftShift - generates code for left shifting */
8335 /*-----------------------------------------------------------------*/
8336 static void genLeftShift (iCode *ic)
8338 operand *left,*right, *result;
8341 symbol *tlbl , *tlbl1;
8344 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8346 right = IC_RIGHT(ic);
8348 result = IC_RESULT(ic);
8350 pic16_aopOp(right,ic,FALSE);
8352 /* if the shift count is known then do it
8353 as efficiently as possible */
8354 if (AOP_TYPE(right) == AOP_LIT) {
8355 genLeftShiftLiteral (left,right,result,ic);
8359 /* shift count is unknown then we have to form
8360 a loop get the loop count in B : Note: we take
8361 only the lower order byte since shifting
8362 more that 32 bits make no sense anyway, ( the
8363 largest size of an object can be only 32 bits ) */
8366 pic16_aopOp(left,ic,FALSE);
8367 pic16_aopOp(result,ic,FALSE);
8369 /* now move the left to the result if they are not the
8371 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8372 AOP_SIZE(result) > 1) {
8374 size = AOP_SIZE(result);
8377 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8378 if (*l == '@' && (IS_AOP_PREG(result))) {
8380 pic16_emitcode("mov","a,%s",l);
8381 pic16_aopPut(AOP(result),"a",offset);
8383 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8384 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8385 //pic16_aopPut(AOP(result),l,offset);
8391 size = AOP_SIZE(result);
8393 /* if it is only one byte then */
8395 if(optimized_for_speed) {
8396 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8397 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8398 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
8399 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8400 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8401 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
8402 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8403 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
8404 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
8405 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
8406 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
8407 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8410 tlbl = newiTempLabel(NULL);
8411 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8412 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8413 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8416 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8417 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8418 pic16_emitpLabel(tlbl->key);
8419 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8420 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8422 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8427 if (pic16_sameRegs(AOP(left),AOP(result))) {
8429 tlbl = newiTempLabel(NULL);
8430 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8431 genMultiAsm(POC_RRCF, result, size,1);
8432 pic16_emitpLabel(tlbl->key);
8433 genMultiAsm(POC_RLCF, result, size,0);
8434 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8436 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8440 //tlbl = newiTempLabel(NULL);
8442 //tlbl1 = newiTempLabel(NULL);
8444 //reAdjustPreg(AOP(result));
8446 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8447 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8448 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8450 //pic16_emitcode("add","a,acc");
8451 //pic16_aopPut(AOP(result),"a",offset++);
8453 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8455 // pic16_emitcode("rlc","a");
8456 // pic16_aopPut(AOP(result),"a",offset++);
8458 //reAdjustPreg(AOP(result));
8460 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8461 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8464 tlbl = newiTempLabel(NULL);
8465 tlbl1= newiTempLabel(NULL);
8467 size = AOP_SIZE(result);
8470 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8472 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8474 /* offset should be 0, 1 or 3 */
8476 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8478 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8480 pic16_emitpcode(POC_MOVWF, pctemp);
8483 pic16_emitpLabel(tlbl->key);
8486 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8488 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
8490 pic16_emitpcode(POC_DECFSZ, pctemp);
8491 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8492 pic16_emitpLabel(tlbl1->key);
8494 pic16_popReleaseTempReg(pctemp);
8498 pic16_freeAsmop (right,NULL,ic,TRUE);
8499 pic16_freeAsmop(left,NULL,ic,TRUE);
8500 pic16_freeAsmop(result,NULL,ic,TRUE);
8503 /*-----------------------------------------------------------------*/
8504 /* genrshOne - right shift a one byte quantity by known count */
8505 /*-----------------------------------------------------------------*/
8506 static void genrshOne (operand *result, operand *left,
8507 int shCount, int sign)
8509 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8510 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8513 /*-----------------------------------------------------------------*/
8514 /* genrshTwo - right shift two bytes by known amount != 0 */
8515 /*-----------------------------------------------------------------*/
8516 static void genrshTwo (operand *result,operand *left,
8517 int shCount, int sign)
8519 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8520 /* if shCount >= 8 */
8524 shiftR1Left2Result(left, MSB16, result, LSB,
8527 movLeft2Result(left, MSB16, result, LSB);
8529 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8532 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8533 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8537 /* 1 <= shCount <= 7 */
8539 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
8542 /*-----------------------------------------------------------------*/
8543 /* shiftRLong - shift right one long from left to result */
8544 /* offl = LSB or MSB16 */
8545 /*-----------------------------------------------------------------*/
8546 static void shiftRLong (operand *left, int offl,
8547 operand *result, int sign)
8549 int size = AOP_SIZE(result);
8550 int same = pic16_sameRegs(AOP(left),AOP(result));
8552 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8554 if (same && (offl == MSB16)) { //shift one byte right
8555 for(i=MSB16;i<size;i++) {
8556 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8557 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8562 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8568 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8570 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8571 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8575 /* add sign of "a" */
8576 pic16_addSign(result, MSB32, sign);
8580 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8582 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8583 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8587 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8589 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8590 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8594 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8597 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8598 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8603 /*-----------------------------------------------------------------*/
8604 /* genrshFour - shift four byte by a known amount != 0 */
8605 /*-----------------------------------------------------------------*/
8606 static void genrshFour (operand *result, operand *left,
8607 int shCount, int sign)
8609 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8610 /* if shifting more that 3 bytes */
8611 if(shCount >= 24 ) {
8614 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8616 movLeft2Result(left, MSB32, result, LSB);
8618 pic16_addSign(result, MSB16, sign);
8620 else if(shCount >= 16){
8623 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8625 movLeft2Result(left, MSB24, result, LSB);
8626 movLeft2Result(left, MSB32, result, MSB16);
8628 pic16_addSign(result, MSB24, sign);
8630 else if(shCount >= 8){
8633 shiftRLong(left, MSB16, result, sign);
8634 else if(shCount == 0){
8635 movLeft2Result(left, MSB16, result, LSB);
8636 movLeft2Result(left, MSB24, result, MSB16);
8637 movLeft2Result(left, MSB32, result, MSB24);
8638 pic16_addSign(result, MSB32, sign);
8640 else{ //shcount >= 2
8641 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8642 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8643 /* the last shift is signed */
8644 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8645 pic16_addSign(result, MSB32, sign);
8648 else{ /* 1 <= shCount <= 7 */
8650 shiftRLong(left, LSB, result, sign);
8652 shiftRLong(result, LSB, result, sign);
8655 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8656 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8657 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8662 /*-----------------------------------------------------------------*/
8663 /* genRightShiftLiteral - right shifting by known count */
8664 /*-----------------------------------------------------------------*/
8665 static void genRightShiftLiteral (operand *left,
8671 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8674 pic16_freeAsmop(right,NULL,ic,TRUE);
8676 pic16_aopOp(left,ic,FALSE);
8677 pic16_aopOp(result,ic,FALSE);
8679 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8682 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8686 lsize = pic16_getDataSize(left);
8687 res_size = pic16_getDataSize(result);
8688 /* test the LEFT size !!! */
8690 /* I suppose that the left size >= result size */
8693 movLeft2Result(left, lsize, result, res_size);
8696 else if(shCount >= (lsize * 8)){
8699 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8701 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8702 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8707 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8708 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8709 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8711 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8716 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8723 genrshOne (result,left,shCount,sign);
8727 genrshTwo (result,left,shCount,sign);
8731 genrshFour (result,left,shCount,sign);
8739 pic16_freeAsmop(left,NULL,ic,TRUE);
8740 pic16_freeAsmop(result,NULL,ic,TRUE);
8743 /*-----------------------------------------------------------------*/
8744 /* genSignedRightShift - right shift of signed number */
8745 /*-----------------------------------------------------------------*/
8746 static void genSignedRightShift (iCode *ic)
8748 operand *right, *left, *result;
8751 symbol *tlbl, *tlbl1 ;
8754 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8756 /* we do it the hard way put the shift count in b
8757 and loop thru preserving the sign */
8758 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8760 right = IC_RIGHT(ic);
8762 result = IC_RESULT(ic);
8764 pic16_aopOp(right,ic,FALSE);
8765 pic16_aopOp(left,ic,FALSE);
8766 pic16_aopOp(result,ic,FALSE);
8769 if ( AOP_TYPE(right) == AOP_LIT) {
8770 genRightShiftLiteral (left,right,result,ic,1);
8773 /* shift count is unknown then we have to form
8774 a loop get the loop count in B : Note: we take
8775 only the lower order byte since shifting
8776 more that 32 bits make no sense anyway, ( the
8777 largest size of an object can be only 32 bits ) */
8779 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8780 //pic16_emitcode("inc","b");
8781 //pic16_freeAsmop (right,NULL,ic,TRUE);
8782 //pic16_aopOp(left,ic,FALSE);
8783 //pic16_aopOp(result,ic,FALSE);
8785 /* now move the left to the result if they are not the
8787 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8788 AOP_SIZE(result) > 1) {
8790 size = AOP_SIZE(result);
8794 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8795 if (*l == '@' && IS_AOP_PREG(result)) {
8797 pic16_emitcode("mov","a,%s",l);
8798 pic16_aopPut(AOP(result),"a",offset);
8800 pic16_aopPut(AOP(result),l,offset);
8802 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8803 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8809 /* mov the highest order bit to OVR */
8810 tlbl = newiTempLabel(NULL);
8811 tlbl1= newiTempLabel(NULL);
8813 size = AOP_SIZE(result);
8816 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8818 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8820 /* offset should be 0, 1 or 3 */
8821 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8823 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8825 pic16_emitpcode(POC_MOVWF, pctemp);
8828 pic16_emitpLabel(tlbl->key);
8830 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
8831 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
8834 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
8837 pic16_emitpcode(POC_DECFSZ, pctemp);
8838 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8839 pic16_emitpLabel(tlbl1->key);
8841 pic16_popReleaseTempReg(pctemp);
8843 size = AOP_SIZE(result);
8845 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8846 pic16_emitcode("rlc","a");
8847 pic16_emitcode("mov","ov,c");
8848 /* if it is only one byte then */
8850 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8852 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8853 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8854 pic16_emitcode("mov","c,ov");
8855 pic16_emitcode("rrc","a");
8856 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8857 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8858 pic16_aopPut(AOP(result),"a",0);
8862 reAdjustPreg(AOP(result));
8863 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8864 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8865 pic16_emitcode("mov","c,ov");
8867 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8869 pic16_emitcode("rrc","a");
8870 pic16_aopPut(AOP(result),"a",offset--);
8872 reAdjustPreg(AOP(result));
8873 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8874 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8879 pic16_freeAsmop(left,NULL,ic,TRUE);
8880 pic16_freeAsmop(result,NULL,ic,TRUE);
8881 pic16_freeAsmop(right,NULL,ic,TRUE);
8884 /*-----------------------------------------------------------------*/
8885 /* genRightShift - generate code for right shifting */
8886 /*-----------------------------------------------------------------*/
8887 static void genRightShift (iCode *ic)
8889 operand *right, *left, *result;
8893 symbol *tlbl, *tlbl1 ;
8895 /* if signed then we do it the hard way preserve the
8896 sign bit moving it inwards */
8897 letype = getSpec(operandType(IC_LEFT(ic)));
8898 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8900 if (!SPEC_USIGN(letype)) {
8901 genSignedRightShift (ic);
8905 /* signed & unsigned types are treated the same : i.e. the
8906 signed is NOT propagated inwards : quoting from the
8907 ANSI - standard : "for E1 >> E2, is equivalent to division
8908 by 2**E2 if unsigned or if it has a non-negative value,
8909 otherwise the result is implementation defined ", MY definition
8910 is that the sign does not get propagated */
8912 right = IC_RIGHT(ic);
8914 result = IC_RESULT(ic);
8916 pic16_aopOp(right,ic,FALSE);
8918 /* if the shift count is known then do it
8919 as efficiently as possible */
8920 if (AOP_TYPE(right) == AOP_LIT) {
8921 genRightShiftLiteral (left,right,result,ic, 0);
8925 /* shift count is unknown then we have to form
8926 a loop get the loop count in B : Note: we take
8927 only the lower order byte since shifting
8928 more that 32 bits make no sense anyway, ( the
8929 largest size of an object can be only 32 bits ) */
8931 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8932 pic16_emitcode("inc","b");
8933 pic16_aopOp(left,ic,FALSE);
8934 pic16_aopOp(result,ic,FALSE);
8936 /* now move the left to the result if they are not the
8938 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8939 AOP_SIZE(result) > 1) {
8941 size = AOP_SIZE(result);
8944 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8945 if (*l == '@' && IS_AOP_PREG(result)) {
8947 pic16_emitcode("mov","a,%s",l);
8948 pic16_aopPut(AOP(result),"a",offset);
8950 pic16_aopPut(AOP(result),l,offset);
8955 tlbl = newiTempLabel(NULL);
8956 tlbl1= newiTempLabel(NULL);
8957 size = AOP_SIZE(result);
8960 /* if it is only one byte then */
8963 tlbl = newiTempLabel(NULL);
8964 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8965 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8966 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8969 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8970 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8971 pic16_emitpLabel(tlbl->key);
8972 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8973 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8975 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8980 reAdjustPreg(AOP(result));
8981 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8982 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8985 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8987 pic16_emitcode("rrc","a");
8988 pic16_aopPut(AOP(result),"a",offset--);
8990 reAdjustPreg(AOP(result));
8992 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8993 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8996 pic16_freeAsmop(left,NULL,ic,TRUE);
8997 pic16_freeAsmop (right,NULL,ic,TRUE);
8998 pic16_freeAsmop(result,NULL,ic,TRUE);
9001 /*-----------------------------------------------------------------*/
9002 /* genUnpackBits - generates code for unpacking bits */
9003 /*-----------------------------------------------------------------*/
9004 static void genUnpackBits (operand *result, char *rname, int ptype)
9011 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9012 etype = getSpec(operandType(result));
9014 /* read the first byte */
9021 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9024 pic16_emitcode("clr","a");
9025 pic16_emitcode("movc","a","@a+dptr");
9030 /* if we have bitdisplacement then it fits */
9031 /* into this byte completely or if length is */
9032 /* less than a byte */
9033 if ((shCnt = SPEC_BSTR(etype)) ||
9034 (SPEC_BLEN(etype) <= 8)) {
9036 /* shift right acc */
9039 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9040 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9042 /* VR -- normally I would use the following, but since we use the hack,
9043 * to avoid the masking from AccRsh, why not mask it right now? */
9046 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9049 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9055 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9056 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9059 /* bit field did not fit in a byte */
9060 rlen = SPEC_BLEN(etype) - 8;
9061 pic16_aopPut(AOP(result),"a",offset++);
9068 pic16_emitcode("inc","%s",rname);
9069 pic16_emitcode("mov","a,@%s",rname);
9073 pic16_emitcode("inc","%s",rname);
9074 pic16_emitcode("movx","a,@%s",rname);
9078 pic16_emitcode("inc","dptr");
9079 pic16_emitcode("movx","a,@dptr");
9083 pic16_emitcode("clr","a");
9084 pic16_emitcode("inc","dptr");
9085 pic16_emitcode("movc","a","@a+dptr");
9089 pic16_emitcode("inc","dptr");
9090 pic16_emitcode("lcall","__gptrget");
9095 /* if we are done */
9099 pic16_aopPut(AOP(result),"a",offset++);
9104 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9105 pic16_aopPut(AOP(result),"a",offset);
9112 static void genDataPointerGet(operand *left,
9116 int size, offset = 0, leoffset=0 ;
9118 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9119 pic16_aopOp(result, ic, FALSE);
9121 size = AOP_SIZE(result);
9122 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9126 /* The following tests may save a redudant movff instruction when
9127 * accessing unions */
9129 /* if they are the same */
9130 if (operandsEqu (left, result)) {
9131 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9137 /* if they are the same registers */
9138 if (pic16_sameRegs(AOP(left),AOP(result))) {
9139 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9145 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9146 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9147 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9154 if ( AOP_TYPE(left) == AOP_PCODE) {
9155 fprintf(stderr,"genDataPointerGet %s, %d\n",
9156 AOP(left)->aopu.pcop->name,
9157 (AOP(left)->aopu.pcop->type == PO_DIR)?
9158 PCOR(AOP(left)->aopu.pcop)->instance:
9159 PCOI(AOP(left)->aopu.pcop)->offset);
9163 if(AOP(left)->aopu.pcop->type == PO_DIR)
9164 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9166 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9169 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9171 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9172 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9173 mov2w(AOP(left), offset); // patch 8
9174 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9176 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9177 pic16_popGet(AOP(left), offset), //patch 8
9178 pic16_popGet(AOP(result), offset)));
9186 pic16_freeAsmop(result,NULL,ic,TRUE);
9189 void pic16_loadFSR0(operand *op)
9191 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9195 /*-----------------------------------------------------------------*/
9196 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
9197 /*-----------------------------------------------------------------*/
9198 static void genNearPointerGet (operand *left,
9203 //regs *preg = NULL ;
9204 sym_link *rtype, *retype;
9205 sym_link *ltype = operandType(left);
9207 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9208 rtype = operandType(result);
9209 retype= getSpec(rtype);
9211 pic16_aopOp(left,ic,FALSE);
9213 // pic16_DumpOp("(left)",left);
9214 // pic16_DumpOp("(result)",result);
9216 /* if left is rematerialisable and
9217 * result is not bit variable type and
9218 * the left is pointer to data space i.e
9219 * lower 128 bytes of space */
9220 if (AOP_TYPE(left) == AOP_PCODE
9221 && !IS_BITFIELD(retype)
9222 && DCL_TYPE(ltype) == POINTER) {
9224 genDataPointerGet (left,result,ic);
9225 pic16_freeAsmop(left, NULL, ic, TRUE);
9229 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9231 /* if the value is already in a pointer register
9232 * then don't need anything more */
9233 if (!AOP_INPREG(AOP(left))) {
9234 /* otherwise get a free pointer register */
9235 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9237 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9238 if( (AOP_TYPE(left) == AOP_PCODE)
9239 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9240 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9242 pic16_loadFSR0( left ); // patch 10
9244 // set up FSR0 with address from left
9245 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9246 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9250 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9252 pic16_aopOp (result,ic,FALSE);
9254 /* if bitfield then unpack the bits */
9255 if (IS_BITFIELD(retype))
9256 genUnpackBits (result, NULL, POINTER);
9258 /* we have can just get the values */
9259 int size = AOP_SIZE(result);
9262 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9265 /* fsr0 is loaded already -- VR */
9266 // pic16_loadFSR0( left );
9268 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9269 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9273 pic16_emitpcode(POC_MOVFF,
9274 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9275 pic16_popGet(AOP(result), offset++)));
9277 pic16_emitpcode(POC_MOVFF,
9278 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9279 pic16_popGet(AOP(result), offset++)));
9283 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9284 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9286 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9290 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9292 pic16_emitcode("mov","a,@%s",rname);
9293 pic16_aopPut(AOP(result),"a",offset);
9295 sprintf(buffer,"@%s",rname);
9296 pic16_aopPut(AOP(result),buffer,offset);
9300 pic16_emitcode("inc","%s",rname);
9305 /* now some housekeeping stuff */
9307 /* we had to allocate for this iCode */
9308 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9309 pic16_freeAsmop(NULL,aop,ic,TRUE);
9311 /* we did not allocate which means left
9312 already in a pointer register, then
9313 if size > 0 && this could be used again
9314 we have to point it back to where it
9316 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9317 if (AOP_SIZE(result) > 1 &&
9318 !OP_SYMBOL(left)->remat &&
9319 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9321 // int size = AOP_SIZE(result) - 1;
9323 // pic16_emitcode("dec","%s",rname);
9328 pic16_freeAsmop(left,NULL,ic,TRUE);
9329 pic16_freeAsmop(result,NULL,ic,TRUE);
9333 /*-----------------------------------------------------------------*/
9334 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
9335 /*-----------------------------------------------------------------*/
9336 static void genPagedPointerGet (operand *left,
9343 sym_link *rtype, *retype;
9345 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9347 rtype = operandType(result);
9348 retype= getSpec(rtype);
9350 pic16_aopOp(left,ic,FALSE);
9352 /* if the value is already in a pointer register
9353 then don't need anything more */
9354 if (!AOP_INPREG(AOP(left))) {
9355 /* otherwise get a free pointer register */
9357 preg = getFreePtr(ic,&aop,FALSE);
9358 pic16_emitcode("mov","%s,%s",
9360 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9361 rname = preg->name ;
9363 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9365 pic16_freeAsmop(left,NULL,ic,TRUE);
9366 pic16_aopOp (result,ic,FALSE);
9368 /* if bitfield then unpack the bits */
9369 if (IS_BITFIELD(retype))
9370 genUnpackBits (result,rname,PPOINTER);
9372 /* we have can just get the values */
9373 int size = AOP_SIZE(result);
9378 pic16_emitcode("movx","a,@%s",rname);
9379 pic16_aopPut(AOP(result),"a",offset);
9384 pic16_emitcode("inc","%s",rname);
9388 /* now some housekeeping stuff */
9390 /* we had to allocate for this iCode */
9391 pic16_freeAsmop(NULL,aop,ic,TRUE);
9393 /* we did not allocate which means left
9394 already in a pointer register, then
9395 if size > 0 && this could be used again
9396 we have to point it back to where it
9398 if (AOP_SIZE(result) > 1 &&
9399 !OP_SYMBOL(left)->remat &&
9400 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9402 int size = AOP_SIZE(result) - 1;
9404 pic16_emitcode("dec","%s",rname);
9409 pic16_freeAsmop(result,NULL,ic,TRUE);
9414 /*-----------------------------------------------------------------*/
9415 /* genFarPointerGet - gget value from far space */
9416 /*-----------------------------------------------------------------*/
9417 static void genFarPointerGet (operand *left,
9418 operand *result, iCode *ic)
9421 sym_link *retype = getSpec(operandType(result));
9423 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9425 pic16_aopOp(left,ic,FALSE);
9427 /* if the operand is already in dptr
9428 then we do nothing else we move the value to dptr */
9429 if (AOP_TYPE(left) != AOP_STR) {
9430 /* if this is remateriazable */
9431 if (AOP_TYPE(left) == AOP_IMMD)
9432 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9433 else { /* we need to get it byte by byte */
9434 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9435 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9436 if (options.model == MODEL_FLAT24)
9438 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9442 /* so dptr know contains the address */
9443 pic16_freeAsmop(left,NULL,ic,TRUE);
9444 pic16_aopOp(result,ic,FALSE);
9446 /* if bit then unpack */
9447 if (IS_BITFIELD(retype))
9448 genUnpackBits(result,"dptr",FPOINTER);
9450 size = AOP_SIZE(result);
9454 pic16_emitcode("movx","a,@dptr");
9455 pic16_aopPut(AOP(result),"a",offset++);
9457 pic16_emitcode("inc","dptr");
9461 pic16_freeAsmop(result,NULL,ic,TRUE);
9464 /*-----------------------------------------------------------------*/
9465 /* genCodePointerGet - get value from code space */
9466 /*-----------------------------------------------------------------*/
9467 static void genCodePointerGet (operand *left,
9468 operand *result, iCode *ic)
9471 sym_link *retype = getSpec(operandType(result));
9473 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9475 pic16_aopOp(left,ic,FALSE);
9477 /* if the operand is already in dptr
9478 then we do nothing else we move the value to dptr */
9479 if (AOP_TYPE(left) != AOP_STR) {
9480 /* if this is remateriazable */
9481 if (AOP_TYPE(left) == AOP_IMMD)
9482 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9483 else { /* we need to get it byte by byte */
9484 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9485 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9486 if (options.model == MODEL_FLAT24)
9488 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9492 /* so dptr know contains the address */
9493 pic16_freeAsmop(left,NULL,ic,TRUE);
9494 pic16_aopOp(result,ic,FALSE);
9496 /* if bit then unpack */
9497 if (IS_BITFIELD(retype))
9498 genUnpackBits(result,"dptr",CPOINTER);
9500 size = AOP_SIZE(result);
9504 pic16_emitcode("clr","a");
9505 pic16_emitcode("movc","a,@a+dptr");
9506 pic16_aopPut(AOP(result),"a",offset++);
9508 pic16_emitcode("inc","dptr");
9512 pic16_freeAsmop(result,NULL,ic,TRUE);
9515 /*-----------------------------------------------------------------*/
9516 /* genGenPointerGet - gget value from generic pointer space */
9517 /*-----------------------------------------------------------------*/
9518 static void genGenPointerGet (operand *left,
9519 operand *result, iCode *ic)
9521 int size, offset, lit;
9522 sym_link *retype = getSpec(operandType(result));
9524 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9525 pic16_aopOp(left,ic,FALSE);
9526 pic16_aopOp(result,ic,FALSE);
9527 size = AOP_SIZE(result);
9529 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9531 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9533 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9534 // load FSR0 from immediate
9535 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9537 // pic16_loadFSR0( left );
9542 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9544 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9551 else { /* we need to get it byte by byte */
9552 // set up FSR0 with address from left
9553 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9554 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9560 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9562 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9569 /* if bit then unpack */
9570 if (IS_BITFIELD(retype))
9571 genUnpackBits(result,"BAD",GPOINTER);
9574 pic16_freeAsmop(left,NULL,ic,TRUE);
9575 pic16_freeAsmop(result,NULL,ic,TRUE);
9579 /*-----------------------------------------------------------------*/
9580 /* genConstPointerGet - get value from const generic pointer space */
9581 /*-----------------------------------------------------------------*/
9582 static void genConstPointerGet (operand *left,
9583 operand *result, iCode *ic)
9585 //sym_link *retype = getSpec(operandType(result));
9586 // symbol *albl = newiTempLabel(NULL); // patch 15
9587 // symbol *blbl = newiTempLabel(NULL); //
9588 // PIC_OPCODE poc; // patch 15
9592 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9593 pic16_aopOp(left,ic,FALSE);
9594 pic16_aopOp(result,ic,TRUE);
9595 size = AOP_SIZE(result);
9597 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9599 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9601 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9602 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9603 pic16_emitpLabel(albl->key);
9605 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9607 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9608 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9609 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9610 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9611 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9613 pic16_emitpLabel(blbl->key);
9615 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9619 // set up table pointer
9620 if( (AOP_TYPE(left) == AOP_PCODE)
9621 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9622 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
9624 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9625 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9626 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9627 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9628 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9629 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9633 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9634 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9635 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9641 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9642 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9646 pic16_freeAsmop(left,NULL,ic,TRUE);
9647 pic16_freeAsmop(result,NULL,ic,TRUE);
9650 /*-----------------------------------------------------------------*/
9651 /* genPointerGet - generate code for pointer get */
9652 /*-----------------------------------------------------------------*/
9653 static void genPointerGet (iCode *ic)
9655 operand *left, *result ;
9656 sym_link *type, *etype;
9659 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9662 result = IC_RESULT(ic) ;
9664 /* depending on the type of pointer we need to
9665 move it to the correct pointer register */
9666 type = operandType(left);
9667 etype = getSpec(type);
9670 if (IS_PTR_CONST(type))
9672 if (IS_CODEPTR(type))
9674 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9676 /* if left is of type of pointer then it is simple */
9677 if (IS_PTR(type) && !IS_FUNC(type->next))
9678 p_type = DCL_TYPE(type);
9680 /* we have to go by the storage class */
9681 p_type = PTR_TYPE(SPEC_OCLS(etype));
9683 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9685 if (SPEC_OCLS(etype)->codesp ) {
9686 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9687 //p_type = CPOINTER ;
9690 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9691 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9692 /*p_type = FPOINTER ;*/
9694 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9695 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9696 /* p_type = PPOINTER; */
9698 if (SPEC_OCLS(etype) == idata )
9699 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9700 /* p_type = IPOINTER; */
9702 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9703 /* p_type = POINTER ; */
9706 /* now that we have the pointer type we assign
9707 the pointer values */
9712 genNearPointerGet (left,result,ic);
9716 genPagedPointerGet(left,result,ic);
9720 genFarPointerGet (left,result,ic);
9724 genConstPointerGet (left,result,ic);
9725 //pic16_emitcodePointerGet (left,result,ic);
9730 if (IS_PTR_CONST(type))
9731 genConstPointerGet (left,result,ic);
9734 genGenPointerGet (left,result,ic);
9740 /*-----------------------------------------------------------------*/
9741 /* genPackBits - generates code for packed bit storage */
9742 /*-----------------------------------------------------------------*/
9743 static void genPackBits (sym_link *etype ,
9745 char *rname, int p_type)
9753 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9754 blen = SPEC_BLEN(etype);
9755 bstr = SPEC_BSTR(etype);
9757 if(AOP_TYPE(right) == AOP_LIT) {
9758 if((blen == 1) && (bstr < 8)) {
9760 /* it is a single bit, so use the appropriate bit instructions */
9762 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9764 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9765 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9767 pic16_emitpcode(POC_BSF,
9768 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9770 pic16_emitpcode(POC_BCF,
9771 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9777 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9780 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9782 /* if the bit lenth is less than or */
9783 /* it exactly fits a byte then */
9784 if((shCnt=SPEC_BSTR(etype))
9785 || SPEC_BLEN(etype) <= 8 ) {
9787 /* shift left acc */
9790 /* using PRODL as a temporary register here */
9791 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9797 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9798 // pic16_emitcode ("mov","b,a");
9799 // pic16_emitcode("mov","a,@%s",rname);
9803 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9804 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9805 (unsigned char)(0xff >> (8-bstr))) ));
9806 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9807 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9814 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9815 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9820 if ( SPEC_BLEN(etype) <= 8 )
9823 pic16_emitcode("inc","%s",rname);
9824 rLen = SPEC_BLEN(etype) ;
9828 /* now generate for lengths greater than one byte */
9831 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9841 pic16_emitcode("mov","@%s,a",rname);
9843 pic16_emitcode("mov","@%s,%s",rname,l);
9848 pic16_emitcode("movx","@dptr,a");
9853 DEBUGpic16_emitcode(";lcall","__gptrput");
9856 pic16_emitcode ("inc","%s",rname);
9861 /* last last was not complete */
9863 /* save the byte & read byte */
9866 pic16_emitcode ("mov","b,a");
9867 pic16_emitcode("mov","a,@%s",rname);
9871 pic16_emitcode ("mov","b,a");
9872 pic16_emitcode("movx","a,@dptr");
9876 pic16_emitcode ("push","b");
9877 pic16_emitcode ("push","acc");
9878 pic16_emitcode ("lcall","__gptrget");
9879 pic16_emitcode ("pop","b");
9883 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9884 pic16_emitcode ("orl","a,b");
9887 if (p_type == GPOINTER)
9888 pic16_emitcode("pop","b");
9893 pic16_emitcode("mov","@%s,a",rname);
9897 pic16_emitcode("movx","@dptr,a");
9901 DEBUGpic16_emitcode(";lcall","__gptrput");
9905 /*-----------------------------------------------------------------*/
9906 /* genDataPointerSet - remat pointer to data space */
9907 /*-----------------------------------------------------------------*/
9908 static void genDataPointerSet(operand *right,
9912 int size, offset = 0, resoffset=0 ;
9914 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9915 pic16_aopOp(right,ic,FALSE);
9917 size = AOP_SIZE(right);
9919 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9922 if ( AOP_TYPE(result) == AOP_PCODE) {
9923 fprintf(stderr,"genDataPointerSet %s, %d\n",
9924 AOP(result)->aopu.pcop->name,
9925 (AOP(result)->aopu.pcop->type == PO_DIR)?
9926 PCOR(AOP(result)->aopu.pcop)->instance:
9927 PCOI(AOP(result)->aopu.pcop)->offset);
9931 if(AOP(result)->aopu.pcop->type == PO_DIR)
9932 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9935 if (AOP_TYPE(right) == AOP_LIT) {
9936 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9938 lit = lit >> (8*offset);
9940 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9941 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9943 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9946 mov2w(AOP(right), offset);
9947 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9953 pic16_freeAsmop(right,NULL,ic,TRUE);
9958 /*-----------------------------------------------------------------*/
9959 /* genNearPointerSet - pic16_emitcode for near pointer put */
9960 /*-----------------------------------------------------------------*/
9961 static void genNearPointerSet (operand *right,
9968 sym_link *ptype = operandType(result);
9971 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9972 retype= getSpec(operandType(right));
9973 resetype = getSpec(operandType(result));
9975 pic16_aopOp(result,ic,FALSE);
9977 /* if the result is rematerializable &
9978 * in data space & not a bit variable */
9980 /* and result is not a bit variable */
9981 if (AOP_TYPE(result) == AOP_PCODE
9982 // && AOP_TYPE(result) == AOP_IMMD
9983 && DCL_TYPE(ptype) == POINTER
9984 && !IS_BITFIELD(retype)
9985 && !IS_BITFIELD(resetype)) {
9987 genDataPointerSet (right,result,ic);
9988 pic16_freeAsmop(result,NULL,ic,TRUE);
9992 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9993 pic16_aopOp(right,ic,FALSE);
9994 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9996 /* if the value is already in a pointer register
9997 * then don't need anything more */
9998 if (!AOP_INPREG(AOP(result))) {
9999 /* otherwise get a free pointer register */
10000 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10002 if( (AOP_TYPE(result) == AOP_PCODE)
10003 && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10004 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10006 pic16_loadFSR0( result ); // patch 10
10008 // set up FSR0 with address of result
10009 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10010 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10015 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10017 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10019 /* if bitfield then unpack the bits */
10020 if (IS_BITFIELD(resetype)) {
10021 genPackBits (resetype, right, NULL, POINTER);
10023 /* we have can just get the values */
10024 int size = AOP_SIZE(right);
10027 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10029 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10032 //pic16_emitcode("mov","@%s,a",rname);
10033 pic16_emitcode("movf","indf0,w ;1");
10036 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
10037 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
10039 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
10041 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
10043 } else { // no literal //
10045 pic16_emitpcode(POC_MOVFF, //
10046 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10047 pic16_popCopyReg(&pic16_pc_postinc0))); //
10049 pic16_emitpcode(POC_MOVFF, //
10050 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10051 pic16_popCopyReg(&pic16_pc_indf0))); //
10059 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10060 /* now some housekeeping stuff */
10062 /* we had to allocate for this iCode */
10063 pic16_freeAsmop(NULL,aop,ic,TRUE);
10065 /* we did not allocate which means left
10066 * already in a pointer register, then
10067 * if size > 0 && this could be used again
10068 * we have to point it back to where it
10070 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10071 if (AOP_SIZE(right) > 1
10072 && !OP_SYMBOL(result)->remat
10073 && ( OP_SYMBOL(result)->liveTo > ic->seq
10076 int size = AOP_SIZE(right) - 1;
10079 pic16_emitcode("decf","fsr0,f");
10080 //pic16_emitcode("dec","%s",rname);
10084 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10087 pic16_freeAsmop(right,NULL,ic,TRUE);
10088 pic16_freeAsmop(result,NULL,ic,TRUE);
10091 /*-----------------------------------------------------------------*/
10092 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
10093 /*-----------------------------------------------------------------*/
10094 static void genPagedPointerSet (operand *right,
10099 regs *preg = NULL ;
10103 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10105 retype= getSpec(operandType(right));
10107 pic16_aopOp(result,ic,FALSE);
10109 /* if the value is already in a pointer register
10110 then don't need anything more */
10111 if (!AOP_INPREG(AOP(result))) {
10112 /* otherwise get a free pointer register */
10114 preg = getFreePtr(ic,&aop,FALSE);
10115 pic16_emitcode("mov","%s,%s",
10117 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10118 rname = preg->name ;
10120 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10122 pic16_freeAsmop(result,NULL,ic,TRUE);
10123 pic16_aopOp (right,ic,FALSE);
10125 /* if bitfield then unpack the bits */
10126 if (IS_BITFIELD(retype))
10127 genPackBits (retype,right,rname,PPOINTER);
10129 /* we have can just get the values */
10130 int size = AOP_SIZE(right);
10134 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10137 pic16_emitcode("movx","@%s,a",rname);
10140 pic16_emitcode("inc","%s",rname);
10146 /* now some housekeeping stuff */
10148 /* we had to allocate for this iCode */
10149 pic16_freeAsmop(NULL,aop,ic,TRUE);
10151 /* we did not allocate which means left
10152 already in a pointer register, then
10153 if size > 0 && this could be used again
10154 we have to point it back to where it
10156 if (AOP_SIZE(right) > 1 &&
10157 !OP_SYMBOL(result)->remat &&
10158 ( OP_SYMBOL(result)->liveTo > ic->seq ||
10160 int size = AOP_SIZE(right) - 1;
10162 pic16_emitcode("dec","%s",rname);
10167 pic16_freeAsmop(right,NULL,ic,TRUE);
10172 /*-----------------------------------------------------------------*/
10173 /* genFarPointerSet - set value from far space */
10174 /*-----------------------------------------------------------------*/
10175 static void genFarPointerSet (operand *right,
10176 operand *result, iCode *ic)
10179 sym_link *retype = getSpec(operandType(right));
10181 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10182 pic16_aopOp(result,ic,FALSE);
10184 /* if the operand is already in dptr
10185 then we do nothing else we move the value to dptr */
10186 if (AOP_TYPE(result) != AOP_STR) {
10187 /* if this is remateriazable */
10188 if (AOP_TYPE(result) == AOP_IMMD)
10189 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10190 else { /* we need to get it byte by byte */
10191 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10192 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10193 if (options.model == MODEL_FLAT24)
10195 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10199 /* so dptr know contains the address */
10200 pic16_freeAsmop(result,NULL,ic,TRUE);
10201 pic16_aopOp(right,ic,FALSE);
10203 /* if bit then unpack */
10204 if (IS_BITFIELD(retype))
10205 genPackBits(retype,right,"dptr",FPOINTER);
10207 size = AOP_SIZE(right);
10211 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10213 pic16_emitcode("movx","@dptr,a");
10215 pic16_emitcode("inc","dptr");
10219 pic16_freeAsmop(right,NULL,ic,TRUE);
10222 /*-----------------------------------------------------------------*/
10223 /* genGenPointerSet - set value from generic pointer space */
10224 /*-----------------------------------------------------------------*/
10225 static void genGenPointerSet (operand *right,
10226 operand *result, iCode *ic)
10228 int i, size, offset, lit;
10229 sym_link *retype = getSpec(operandType(right));
10231 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10233 pic16_aopOp(result,ic,FALSE);
10234 pic16_aopOp(right,ic,FALSE);
10235 size = AOP_SIZE(right);
10238 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10240 /* if the operand is already in dptr
10241 then we do nothing else we move the value to dptr */
10242 if (AOP_TYPE(result) != AOP_STR) {
10243 /* if this is remateriazable */
10244 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10245 // WARNING: anythig until "else" is untested!
10246 if (AOP_TYPE(result) == AOP_IMMD) {
10247 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10248 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10249 // load FSR0 from immediate
10250 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10254 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10256 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10262 else { /* we need to get it byte by byte */
10263 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10264 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10266 // set up FSR0 with address of result
10267 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10268 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10270 /* hack hack! see if this the FSR. If so don't load W */
10271 if(AOP_TYPE(right) != AOP_ACC) {
10273 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10275 if(AOP_TYPE(right) == AOP_LIT)
10278 // note: pic16_popGet handles sign extension
10279 for(i=0;i<size;i++) {
10280 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10282 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10284 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10289 for(i=0;i<size;i++) {
10291 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10292 pic16_popCopyReg(&pic16_pc_postinc0)));
10294 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10295 pic16_popCopyReg(&pic16_pc_indf0)));
10301 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10302 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10304 } // if (AOP_TYPE(result) != AOP_IMMD)
10306 } // if (AOP_TYPE(result) != AOP_STR)
10307 /* so dptr know contains the address */
10310 /* if bit then unpack */
10311 if (IS_BITFIELD(retype))
10312 genPackBits(retype,right,"dptr",GPOINTER);
10314 size = AOP_SIZE(right);
10317 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
10319 // set up FSR0 with address of result
10320 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10321 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10324 if (AOP_TYPE(right) == AOP_LIT) {
10325 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10327 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10329 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10331 } else { // no literal
10333 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10335 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10343 pic16_freeAsmop(right,NULL,ic,TRUE);
10344 pic16_freeAsmop(result,NULL,ic,TRUE);
10347 /*-----------------------------------------------------------------*/
10348 /* genPointerSet - stores the value into a pointer location */
10349 /*-----------------------------------------------------------------*/
10350 static void genPointerSet (iCode *ic)
10352 operand *right, *result ;
10353 sym_link *type, *etype;
10356 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10358 right = IC_RIGHT(ic);
10359 result = IC_RESULT(ic) ;
10361 /* depending on the type of pointer we need to
10362 move it to the correct pointer register */
10363 type = operandType(result);
10364 etype = getSpec(type);
10365 /* if left is of type of pointer then it is simple */
10366 if (IS_PTR(type) && !IS_FUNC(type->next)) {
10367 p_type = DCL_TYPE(type);
10370 /* we have to go by the storage class */
10371 p_type = PTR_TYPE(SPEC_OCLS(etype));
10373 /* if (SPEC_OCLS(etype)->codesp ) { */
10374 /* p_type = CPOINTER ; */
10377 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10378 /* p_type = FPOINTER ; */
10380 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10381 /* p_type = PPOINTER ; */
10383 /* if (SPEC_OCLS(etype) == idata ) */
10384 /* p_type = IPOINTER ; */
10386 /* p_type = POINTER ; */
10389 /* now that we have the pointer type we assign
10390 the pointer values */
10395 genNearPointerSet (right,result,ic);
10399 genPagedPointerSet (right,result,ic);
10403 genFarPointerSet (right,result,ic);
10407 genGenPointerSet (right,result,ic);
10411 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10412 "genPointerSet: illegal pointer type");
10416 /*-----------------------------------------------------------------*/
10417 /* genIfx - generate code for Ifx statement */
10418 /*-----------------------------------------------------------------*/
10419 static void genIfx (iCode *ic, iCode *popIc)
10421 operand *cond = IC_COND(ic);
10424 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10426 pic16_aopOp(cond,ic,FALSE);
10428 /* get the value into acc */
10429 if (AOP_TYPE(cond) != AOP_CRY)
10430 pic16_toBoolean(cond);
10433 /* the result is now in the accumulator */
10434 pic16_freeAsmop(cond,NULL,ic,TRUE);
10436 /* if there was something to be popped then do it */
10440 /* if the condition is a bit variable */
10441 if (isbit && IS_ITEMP(cond) &&
10443 genIfxJump(ic,SPIL_LOC(cond)->rname);
10444 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10447 if (isbit && !IS_ITEMP(cond))
10448 genIfxJump(ic,OP_SYMBOL(cond)->rname);
10450 genIfxJump(ic,"a");
10456 /*-----------------------------------------------------------------*/
10457 /* genAddrOf - generates code for address of */
10458 /*-----------------------------------------------------------------*/
10459 static void genAddrOf (iCode *ic)
10461 operand *result, *left;
10463 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
10464 pCodeOp *pcop0, *pcop1, *pcop2;
10466 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10468 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10469 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10471 sym = OP_SYMBOL( left );
10473 size = AOP_SIZE(IC_RESULT(ic));
10475 // if(pic16_debug_verbose) {
10476 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10477 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10480 /* Assume that what we want the address of is in data space
10481 * since there is no stack on the PIC, yet! -- VR */
10483 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10486 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10489 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10493 pic16_emitpcode(POC_MOVLW, pcop0);
10494 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10495 pic16_emitpcode(POC_MOVLW, pcop1);
10496 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10497 pic16_emitpcode(POC_MOVLW, pcop2);
10498 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
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));
10506 pic16_emitpcode(POC_MOVLW, pcop0);
10507 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10510 pic16_freeAsmop(result,NULL,ic,TRUE);
10511 pic16_freeAsmop(left, NULL, ic, FALSE);
10516 /*-----------------------------------------------------------------*/
10517 /* genFarFarAssign - assignment when both are in far space */
10518 /*-----------------------------------------------------------------*/
10519 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10521 int size = AOP_SIZE(right);
10524 /* first push the right side on to the stack */
10526 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10528 pic16_emitcode ("push","acc");
10531 pic16_freeAsmop(right,NULL,ic,FALSE);
10532 /* now assign DPTR to result */
10533 pic16_aopOp(result,ic,FALSE);
10534 size = AOP_SIZE(result);
10536 pic16_emitcode ("pop","acc");
10537 pic16_aopPut(AOP(result),"a",--offset);
10539 pic16_freeAsmop(result,NULL,ic,FALSE);
10544 /*-----------------------------------------------------------------*/
10545 /* genAssign - generate code for assignment */
10546 /*-----------------------------------------------------------------*/
10547 static void genAssign (iCode *ic)
10549 operand *result, *right;
10550 int size, offset,know_W;
10551 unsigned long lit = 0L;
10553 result = IC_RESULT(ic);
10554 right = IC_RIGHT(ic) ;
10556 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10558 /* if they are the same */
10559 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10562 pic16_aopOp(right,ic,FALSE);
10563 pic16_aopOp(result,ic,TRUE);
10565 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10567 /* if they are the same registers */
10568 if (pic16_sameRegs(AOP(right),AOP(result)))
10571 /* if the result is a bit */
10572 if (AOP_TYPE(result) == AOP_CRY) {
10573 /* if the right size is a literal then
10574 we know what the value is */
10575 if (AOP_TYPE(right) == AOP_LIT) {
10577 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10578 pic16_popGet(AOP(result),0));
10580 if (((int) operandLitValue(right)))
10581 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10582 AOP(result)->aopu.aop_dir,
10583 AOP(result)->aopu.aop_dir);
10585 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10586 AOP(result)->aopu.aop_dir,
10587 AOP(result)->aopu.aop_dir);
10591 /* the right is also a bit variable */
10592 if (AOP_TYPE(right) == AOP_CRY) {
10593 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10594 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10595 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10597 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10598 AOP(result)->aopu.aop_dir,
10599 AOP(result)->aopu.aop_dir);
10600 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10601 AOP(right)->aopu.aop_dir,
10602 AOP(right)->aopu.aop_dir);
10603 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10604 AOP(result)->aopu.aop_dir,
10605 AOP(result)->aopu.aop_dir);
10609 /* we need to or */
10610 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10611 pic16_toBoolean(right);
10613 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10614 //pic16_aopPut(AOP(result),"a",0);
10618 /* bit variables done */
10620 size = AOP_SIZE(result);
10623 if(AOP_TYPE(right) == AOP_LIT) {
10624 if(!IS_FLOAT(operandType( right )))
10625 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10628 unsigned long lit_int;
10632 /* take care if literal is a float */
10633 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10634 lit = info.lit_int;
10638 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10639 // sizeof(unsigned long int), sizeof(float));
10641 if(AOP_TYPE(right) != AOP_LIT
10642 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10643 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10645 // set up table pointer
10646 if( (AOP_TYPE(right) == AOP_PCODE)
10647 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10648 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10650 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10651 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10652 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10653 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10654 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10655 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10657 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10658 pic16_popCopyReg(&pic16_pc_tblptrl)));
10659 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10660 pic16_popCopyReg(&pic16_pc_tblptrh)));
10661 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10662 pic16_popCopyReg(&pic16_pc_tblptru)));
10665 size = min(AOP_SIZE(right), AOP_SIZE(result));
10667 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10668 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10669 pic16_popGet(AOP(result),offset)));
10673 if(AOP_SIZE(result) > AOP_SIZE(right)) {
10674 size = AOP_SIZE(result) - AOP_SIZE(right);
10676 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10685 /* VR - What is this?! */
10686 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10687 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10688 if(aopIdx(AOP(result),0) == 4) {
10689 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10691 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10692 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10696 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10701 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10702 if(AOP_TYPE(right) == AOP_LIT) {
10704 if(know_W != (lit&0xff))
10705 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10707 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10709 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10713 } else if (AOP_TYPE(right) == AOP_CRY) {
10714 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10716 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10717 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10719 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10720 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10721 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10723 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10726 /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10727 normally should work, but mind that the W register live range
10728 is not checked, so if the code generator assumes that the W
10729 is already loaded after such a pair, wrong code will be generated.
10731 Checking the live range is the next step.
10732 This is experimental code yet and has not been fully tested yet.
10733 USE WITH CARE. Revert to old code by setting 0 to the condition above.
10734 Vangelis Rokas 030603 (vrokas@otenet.gr) */
10736 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10738 /* This is the old code, which is assumed(?!) that works fine(!?) */
10740 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10741 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10750 pic16_freeAsmop (right,NULL,ic,FALSE);
10751 pic16_freeAsmop (result,NULL,ic,TRUE);
10754 /*-----------------------------------------------------------------*/
10755 /* genJumpTab - generates code for jump table */
10756 /*-----------------------------------------------------------------*/
10757 static void genJumpTab (iCode *ic)
10762 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10764 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10765 /* get the condition into accumulator */
10766 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10768 /* multiply by three */
10769 pic16_emitcode("add","a,acc");
10770 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10772 jtab = newiTempLabel(NULL);
10773 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10774 pic16_emitcode("jmp","@a+dptr");
10775 pic16_emitcode("","%05d_DS_:",jtab->key+100);
10777 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10778 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10780 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10781 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10782 pic16_emitpLabel(jtab->key);
10784 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10786 /* now generate the jump labels */
10787 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10788 jtab = setNextItem(IC_JTLABELS(ic))) {
10789 pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10790 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10796 /*-----------------------------------------------------------------*/
10797 /* genMixedOperation - gen code for operators between mixed types */
10798 /*-----------------------------------------------------------------*/
10800 TSD - Written for the PIC port - but this unfortunately is buggy.
10801 This routine is good in that it is able to efficiently promote
10802 types to different (larger) sizes. Unfortunately, the temporary
10803 variables that are optimized out by this routine are sometimes
10804 used in other places. So until I know how to really parse the
10805 iCode tree, I'm going to not be using this routine :(.
10807 static int genMixedOperation (iCode *ic)
10810 operand *result = IC_RESULT(ic);
10811 sym_link *ctype = operandType(IC_LEFT(ic));
10812 operand *right = IC_RIGHT(ic);
10818 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10820 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10826 nextright = IC_RIGHT(nextic);
10827 nextleft = IC_LEFT(nextic);
10828 nextresult = IC_RESULT(nextic);
10830 pic16_aopOp(right,ic,FALSE);
10831 pic16_aopOp(result,ic,FALSE);
10832 pic16_aopOp(nextright, nextic, FALSE);
10833 pic16_aopOp(nextleft, nextic, FALSE);
10834 pic16_aopOp(nextresult, nextic, FALSE);
10836 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10838 operand *t = right;
10842 pic16_emitcode(";remove right +","");
10844 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10846 operand *t = right;
10850 pic16_emitcode(";remove left +","");
10854 big = AOP_SIZE(nextleft);
10855 small = AOP_SIZE(nextright);
10857 switch(nextic->op) {
10860 pic16_emitcode(";optimize a +","");
10861 /* if unsigned or not an integral type */
10862 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10863 pic16_emitcode(";add a bit to something","");
10866 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10868 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10869 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10870 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10872 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10880 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10881 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10882 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10885 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10887 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10888 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10889 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10890 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10891 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10894 pic16_emitcode("rlf","known_zero,w");
10901 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10902 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10903 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10905 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10915 pic16_freeAsmop(right,NULL,ic,TRUE);
10916 pic16_freeAsmop(result,NULL,ic,TRUE);
10917 pic16_freeAsmop(nextright,NULL,ic,TRUE);
10918 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10920 nextic->generated = 1;
10927 /*-----------------------------------------------------------------*/
10928 /* genCast - gen code for casting */
10929 /*-----------------------------------------------------------------*/
10930 static void genCast (iCode *ic)
10932 operand *result = IC_RESULT(ic);
10933 sym_link *ctype = operandType(IC_LEFT(ic));
10934 sym_link *rtype = operandType(IC_RIGHT(ic));
10935 operand *right = IC_RIGHT(ic);
10938 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10939 /* if they are equivalent then do nothing */
10940 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10943 pic16_aopOp(right,ic,FALSE) ;
10944 pic16_aopOp(result,ic,FALSE);
10946 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10948 /* if the result is a bit */
10949 if (AOP_TYPE(result) == AOP_CRY) {
10951 /* if the right size is a literal then
10952 * we know what the value is */
10953 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10955 if (AOP_TYPE(right) == AOP_LIT) {
10956 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10957 pic16_popGet(AOP(result),0));
10959 if (((int) operandLitValue(right)))
10960 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10961 AOP(result)->aopu.aop_dir,
10962 AOP(result)->aopu.aop_dir);
10964 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10965 AOP(result)->aopu.aop_dir,
10966 AOP(result)->aopu.aop_dir);
10970 /* the right is also a bit variable */
10971 if (AOP_TYPE(right) == AOP_CRY) {
10973 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10975 pic16_emitcode("clrc","");
10976 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10977 AOP(right)->aopu.aop_dir,
10978 AOP(right)->aopu.aop_dir);
10979 pic16_aopPut(AOP(result),"c",0);
10983 /* we need to or */
10984 if (AOP_TYPE(right) == AOP_REG) {
10985 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10986 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10987 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10989 pic16_toBoolean(right);
10990 pic16_aopPut(AOP(result),"a",0);
10994 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10997 size = AOP_SIZE(result);
10999 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11001 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
11002 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11003 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
11006 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11011 /* if they are the same size : or less */
11012 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11014 /* if they are in the same place */
11015 if (pic16_sameRegs(AOP(right),AOP(result)))
11018 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11020 if (IS_PTR_CONST(rtype))
11022 if (IS_CODEPTR(rtype))
11024 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11027 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11029 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11031 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11034 if(AOP_TYPE(right) == AOP_IMMD) {
11035 pCodeOp *pcop0, *pcop1, *pcop2;
11036 symbol *sym = OP_SYMBOL( right );
11038 size = AOP_SIZE(result);
11040 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11042 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11044 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11047 pic16_emitpcode(POC_MOVLW, pcop0);
11048 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11049 pic16_emitpcode(POC_MOVLW, pcop1);
11050 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11051 pic16_emitpcode(POC_MOVLW, pcop2);
11052 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
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));
11060 pic16_emitpcode(POC_MOVLW, pcop0);
11061 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11065 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11066 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11067 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11068 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11069 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11070 if(AOP_SIZE(result) <2)
11071 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11073 /* if they in different places then copy */
11074 size = AOP_SIZE(result);
11077 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11078 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11085 /* if the result is of type pointer */
11086 if (IS_PTR(ctype)) {
11088 sym_link *type = operandType(right);
11089 sym_link *etype = getSpec(type);
11091 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
11093 /* pointer to generic pointer */
11094 if (IS_GENPTR(ctype)) {
11098 p_type = DCL_TYPE(type);
11100 /* we have to go by the storage class */
11101 p_type = PTR_TYPE(SPEC_OCLS(etype));
11103 /* if (SPEC_OCLS(etype)->codesp ) */
11104 /* p_type = CPOINTER ; */
11106 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11107 /* p_type = FPOINTER ; */
11109 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11110 /* p_type = PPOINTER; */
11112 /* if (SPEC_OCLS(etype) == idata ) */
11113 /* p_type = IPOINTER ; */
11115 /* p_type = POINTER ; */
11118 /* the first two bytes are known */
11119 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
11120 size = GPTRSIZE - 1;
11123 if(offset < AOP_SIZE(right)) {
11124 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
11125 if ((AOP_TYPE(right) == AOP_PCODE) &&
11126 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11127 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11128 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11130 pic16_aopPut(AOP(result),
11131 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11135 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11138 /* the last byte depending on type */
11142 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11145 pic16_emitcode(";BUG!? ","%d",__LINE__);
11149 pic16_emitcode(";BUG!? ","%d",__LINE__);
11153 pic16_emitcode(";BUG!? ","%d",__LINE__);
11158 /* this should never happen */
11159 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11160 "got unknown pointer type");
11163 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
11167 /* just copy the pointers */
11168 size = AOP_SIZE(result);
11171 pic16_aopPut(AOP(result),
11172 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11181 /* so we now know that the size of destination is greater
11182 than the size of the source.
11183 Now, if the next iCode is an operator then we might be
11184 able to optimize the operation without performing a cast.
11186 if(genMixedOperation(ic))
11189 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11191 /* we move to result for the size of source */
11192 size = AOP_SIZE(right);
11195 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11196 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11200 /* now depending on the sign of the destination */
11201 size = AOP_SIZE(result) - AOP_SIZE(right);
11202 /* if unsigned or not an integral type */
11203 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11205 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11207 /* we need to extend the sign :( */
11210 /* Save one instruction of casting char to int */
11211 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11212 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11213 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
11215 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11218 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11220 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
11222 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
11225 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
11230 pic16_freeAsmop(right,NULL,ic,TRUE);
11231 pic16_freeAsmop(result,NULL,ic,TRUE);
11235 /*-----------------------------------------------------------------*/
11236 /* genDjnz - generate decrement & jump if not zero instrucion */
11237 /*-----------------------------------------------------------------*/
11238 static int genDjnz (iCode *ic, iCode *ifx)
11240 symbol *lbl, *lbl1;
11241 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11246 /* if the if condition has a false label
11247 then we cannot save */
11251 /* if the minus is not of the form
11253 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11254 !IS_OP_LITERAL(IC_RIGHT(ic)))
11257 if (operandLitValue(IC_RIGHT(ic)) != 1)
11260 /* if the size of this greater than one then no
11262 if (getSize(operandType(IC_RESULT(ic))) > 1)
11265 /* otherwise we can save BIG */
11266 lbl = newiTempLabel(NULL);
11267 lbl1= newiTempLabel(NULL);
11269 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11271 if (IS_AOP_PREG(IC_RESULT(ic))) {
11272 pic16_emitcode("dec","%s",
11273 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11274 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11275 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11279 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11280 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11282 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11283 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
11286 /* pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11287 /* pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11288 /* pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11289 /* pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11292 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11293 ifx->generated = 1;
11297 /*-----------------------------------------------------------------*/
11298 /* genReceive - generate code for a receive iCode */
11299 /*-----------------------------------------------------------------*/
11300 static void genReceive (iCode *ic)
11302 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11304 if (isOperandInFarSpace(IC_RESULT(ic)) &&
11305 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11306 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11308 int size = getSize(operandType(IC_RESULT(ic)));
11309 int offset = pic16_fReturnSizePic - size;
11312 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11313 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11317 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
11319 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11320 size = AOP_SIZE(IC_RESULT(ic));
11323 pic16_emitcode ("pop","acc");
11324 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11327 DEBUGpic16_emitcode ("; ***","2 %s %d",__FUNCTION__,__LINE__);
11330 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11332 assignResultValue(IC_RESULT(ic), 0);
11335 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11338 /*-----------------------------------------------------------------*/
11339 /* genDummyRead - generate code for dummy read of volatiles */
11340 /*-----------------------------------------------------------------*/
11342 genDummyRead (iCode * ic)
11344 pic16_emitcode ("; genDummyRead","");
11345 pic16_emitcode ("; not implemented","");
11350 /*-----------------------------------------------------------------*/
11351 /* genpic16Code - generate code for pic16 based controllers */
11352 /*-----------------------------------------------------------------*/
11354 * At this point, ralloc.c has gone through the iCode and attempted
11355 * to optimize in a way suitable for a PIC. Now we've got to generate
11356 * PIC instructions that correspond to the iCode.
11358 * Once the instructions are generated, we'll pass through both the
11359 * peep hole optimizer and the pCode optimizer.
11360 *-----------------------------------------------------------------*/
11362 void genpic16Code (iCode *lic)
11367 lineHead = lineCurr = NULL;
11369 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11370 pic16_addpBlock(pb);
11373 /* if debug information required */
11374 if (options.debug && currFunc) {
11376 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11381 for (ic = lic ; ic ; ic = ic->next ) {
11383 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11384 if ( cln != ic->lineno ) {
11385 if ( options.debug ) {
11386 debugFile->writeCLine (ic);
11389 if(!options.noCcodeInAsm) {
11390 pic16_addpCode2pBlock(pb,
11391 pic16_newpCodeCSource(ic->lineno, ic->filename,
11392 printCLine(ic->filename, ic->lineno)));
11398 if(options.iCodeInAsm) {
11400 /* insert here code to print iCode as comment */
11401 l = Safe_strdup(printILine(ic));
11402 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11405 /* if the result is marked as
11406 spilt and rematerializable or code for
11407 this has already been generated then
11409 if (resultRemat(ic) || ic->generated )
11412 /* depending on the operation */
11431 /* IPOP happens only when trying to restore a
11432 spilt live range, if there is an ifx statement
11433 following this pop then the if statement might
11434 be using some of the registers being popped which
11435 would destroy the contents of the register so
11436 we need to check for this condition and handle it */
11438 ic->next->op == IFX &&
11439 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
11440 genIfx (ic->next,ic);
11458 genEndFunction (ic);
11474 pic16_genPlus (ic) ;
11478 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11479 pic16_genMinus (ic);
11495 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
11499 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11506 /* note these two are xlated by algebraic equivalence
11507 during parsing SDCC.y */
11508 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11509 "got '>=' or '<=' shouldn't have come here");
11513 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11525 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11529 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11533 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11557 genRightShift (ic);
11560 case GET_VALUE_AT_ADDRESS:
11565 if (POINTER_SET(ic))
11592 addSet(&_G.sendSet,ic);
11595 case DUMMY_READ_VOLATILE:
11605 /* now we are ready to call the
11606 peep hole optimizer */
11607 if (!options.nopeep) {
11608 peepHole (&lineHead);
11610 /* now do the actual printing */
11611 printLine (lineHead,codeOutFile);
11614 DFPRINTF((stderr,"printing pBlock\n\n"));
11615 pic16_printpBlock(stdout,pb);