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 int pic16_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+pic16_labelOffset));
276 void pic16_emitpLabelFORCE(int key)
278 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_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,pic16_labelOffset);
510 /*-----------------------------------------------------------------*/
511 /* pointerCode - returns the code for a pointer type */
512 /*-----------------------------------------------------------------*/
513 static int pointerCode (sym_link *etype)
516 return PTR_TYPE(SPEC_OCLS(etype));
521 /*-----------------------------------------------------------------*/
522 /* aopForSym - for a true symbol */
523 /*-----------------------------------------------------------------*/
524 static asmop *aopForSym (iCode *ic, operand *op, bool result)
526 symbol *sym=OP_SYMBOL(op);
528 memmap *space= SPEC_OCLS(sym->etype);
530 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
532 // sym = OP_SYMBOL(op);
534 /* if already has one */
536 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
540 /* if symbol was initially placed onStack then we must re-place it
541 * to direct memory, since pic16 does not have a specific stack */
544 SPEC_OCLS( sym->etype ) = data;
550 /* assign depending on the storage class */
551 /* if it is on the stack or indirectly addressable */
552 /* space we need to assign either r0 or r1 to it */
553 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
555 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
556 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
558 sym->aop = aop = newAsmop(0);
559 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
560 aop->size = getSize(sym->type);
562 /* now assign the address of the variable to
563 the pointer register */
564 if (aop->type != AOP_STK) {
568 pic16_emitcode("push","acc");
570 pic16_emitcode("mov","a,_bp");
571 pic16_emitcode("add","a,#0x%02x",
573 ((char)(sym->stack - _G.nRegsSaved )) :
574 ((char)sym->stack)) & 0xff);
575 pic16_emitcode("mov","%s,a",
576 aop->aopu.aop_ptr->name);
579 pic16_emitcode("pop","acc");
581 pic16_emitcode("mov","%s,#%s",
582 aop->aopu.aop_ptr->name,
584 aop->paged = space->paged;
586 aop->aopu.aop_stk = sym->stack;
591 if (sym->onStack && options.stack10bit)
593 /* It's on the 10 bit stack, which is located in
597 //DEBUGpic16_emitcode(";","%d",__LINE__);
600 pic16_emitcode("push","acc");
602 pic16_emitcode("mov","a,_bp");
603 pic16_emitcode("add","a,#0x%02x",
605 ((char)(sym->stack - _G.nRegsSaved )) :
606 ((char)sym->stack)) & 0xff);
609 pic16_emitcode ("mov","dpx1,#0x40");
610 pic16_emitcode ("mov","dph1,#0x00");
611 pic16_emitcode ("mov","dpl1, a");
615 pic16_emitcode("pop","acc");
617 sym->aop = aop = newAsmop(AOP_DPTR2);
618 aop->size = getSize(sym->type);
622 //DEBUGpic16_emitcode(";","%d",__LINE__);
623 /* if in bit space */
624 if (IN_BITSPACE(space)) {
625 sym->aop = aop = newAsmop (AOP_CRY);
626 aop->aopu.aop_dir = sym->rname ;
627 aop->size = getSize(sym->type);
628 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
631 /* if it is in direct space */
632 if (IN_DIRSPACE(space)) {
633 sym->aop = aop = newAsmop (AOP_DIR);
634 aop->aopu.aop_dir = sym->rname ;
635 aop->size = getSize(sym->type);
636 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
637 pic16_allocDirReg( IC_LEFT(ic) );
642 /* special case for a function */
643 if (IS_FUNC(sym->type)) {
644 sym->aop = aop = newAsmop(AOP_IMMD);
645 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
646 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
647 strcpy(aop->aopu.aop_immd,sym->rname);
648 aop->size = FPTRSIZE;
649 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
655 /* only remaining is far space */
656 /* in which case DPTR gets the address */
657 sym->aop = aop = newAsmop(AOP_PCODE);
659 /* change the next if to 1 to revert to good old immediate code */
660 if(IN_CODESPACE(space)) {
661 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
662 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
663 PCOI(aop->aopu.pcop)->index = 0;
665 /* try to allocate via direct register */
666 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
667 // aop->size = getSize( sym->type );
670 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
671 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
674 if(!pic16_allocDirReg (IC_LEFT(ic)))
678 if(IN_DIRSPACE( space ))
680 else if(IN_CODESPACE( space ))
681 aop->size = FPTRSIZE;
682 else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
683 else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
688 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
690 /* if it is in code space */
691 if (IN_CODESPACE(space))
697 /*-----------------------------------------------------------------*/
698 /* aopForRemat - rematerialzes an object */
699 /*-----------------------------------------------------------------*/
700 static asmop *aopForRemat (operand *op) // x symbol *sym)
702 symbol *sym = OP_SYMBOL(op);
703 iCode *ic = NULL, *oldic;
704 asmop *aop = newAsmop(AOP_PCODE);
710 ic = sym->rematiCode;
712 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
714 if(IS_OP_POINTER(op)) {
715 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
721 // pic16_emitpcomment("ic: %s\n", printILine(ic));
724 val += (int) operandLitValue(IC_RIGHT(ic));
725 } else if (ic->op == '-') {
726 val -= (int) operandLitValue(IC_RIGHT(ic));
730 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
733 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
735 if(!op->isaddr)viaimmd++; else viaimmd=0;
737 /* set the following if to 1 to revert to good old immediate code */
738 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
741 DEBUGpic16_emitcode("%s:%d immediate", __FILE__, __LINE__);
743 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
746 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
748 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
751 PCOI(aop->aopu.pcop)->index = val;
753 DEBUGpic16_emitcode("%s:%d dir", __FILE__, __LINE__);
755 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
756 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
757 // aop->size = AOP_SIZE( IC_LEFT(ic) );
761 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
762 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
764 val, IS_PTR_CONST(operandType(op)));
766 val, IS_CODEPTR(operandType(op)));
769 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
771 pic16_allocDirReg (IC_LEFT(ic));
773 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
779 static int aopIdx (asmop *aop, int offset)
784 if(aop->type != AOP_REG)
787 return aop->aopu.aop_reg[offset]->rIdx;
790 /*-----------------------------------------------------------------*/
791 /* regsInCommon - two operands have some registers in common */
792 /*-----------------------------------------------------------------*/
793 static bool regsInCommon (operand *op1, operand *op2)
798 /* if they have registers in common */
799 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
802 sym1 = OP_SYMBOL(op1);
803 sym2 = OP_SYMBOL(op2);
805 if (sym1->nRegs == 0 || sym2->nRegs == 0)
808 for (i = 0 ; i < sym1->nRegs ; i++) {
813 for (j = 0 ; j < sym2->nRegs ;j++ ) {
817 if (sym2->regs[j] == sym1->regs[i])
825 /*-----------------------------------------------------------------*/
826 /* operandsEqu - equivalent */
827 /*-----------------------------------------------------------------*/
828 static bool operandsEqu ( operand *op1, operand *op2)
832 /* if they not symbols */
833 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
836 sym1 = OP_SYMBOL(op1);
837 sym2 = OP_SYMBOL(op2);
839 /* if both are itemps & one is spilt
840 and the other is not then false */
841 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
842 sym1->isspilt != sym2->isspilt )
845 /* if they are the same */
849 if (sym1->rname[0] && sym2->rname[0]
850 && strcmp (sym1->rname, sym2->rname) == 0)
854 /* if left is a tmp & right is not */
858 (sym1->usl.spillLoc == sym2))
865 (sym2->usl.spillLoc == sym1))
871 /*-----------------------------------------------------------------*/
872 /* pic16_sameRegs - two asmops have the same registers */
873 /*-----------------------------------------------------------------*/
874 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
881 if (aop1->type != AOP_REG ||
882 aop2->type != AOP_REG )
885 if (aop1->size != aop2->size )
888 for (i = 0 ; i < aop1->size ; i++ )
889 if (aop1->aopu.aop_reg[i] !=
890 aop2->aopu.aop_reg[i] )
896 /*-----------------------------------------------------------------*/
897 /* pic16_aopOp - allocates an asmop for an operand : */
898 /*-----------------------------------------------------------------*/
899 void pic16_aopOp (operand *op, iCode *ic, bool result)
908 // DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
910 /* if this a literal */
911 if (IS_OP_LITERAL(op)) {
912 op->aop = aop = newAsmop(AOP_LIT);
913 aop->aopu.aop_lit = op->operand.valOperand;
914 aop->size = getSize(operandType(op));
919 sym_link *type = operandType(op);
921 if(IS_PTR_CONST(type))
925 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
928 /* if already has a asmop then continue */
932 /* if the underlying symbol has a aop */
933 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
934 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
935 op->aop = OP_SYMBOL(op)->aop;
939 /* if this is a true symbol */
940 if (IS_TRUE_SYMOP(op)) {
941 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
942 op->aop = aopForSym(ic, op, result);
946 /* this is a temporary : this has
952 e) can be a return use only */
956 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
957 /* if the type is a conditional */
958 if (sym->regType == REG_CND) {
959 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
964 /* if it is spilt then two situations
966 b) has a spill location */
967 if (sym->isspilt || sym->nRegs == 0) {
969 DEBUGpic16_emitcode(";","%d",__LINE__);
970 /* rematerialize it NOW */
973 sym->aop = op->aop = aop =
975 aop->size = getSize(sym->type);
976 //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
983 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
984 aop->size = getSize(sym->type);
985 for ( i = 0 ; i < 1 ; i++ ) {
986 aop->aopu.aop_str[i] = accUse[i];
987 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
989 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
990 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
998 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
999 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1000 //pic16_allocDirReg (IC_LEFT(ic));
1001 aop->size = getSize(sym->type);
1006 aop = op->aop = sym->aop = newAsmop(AOP_STR);
1007 aop->size = getSize(sym->type);
1008 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1009 aop->aopu.aop_str[i] = fReturn[i];
1011 DEBUGpic16_emitcode(";","%d",__LINE__);
1015 /* else spill location */
1016 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1017 /* force a new aop if sizes differ */
1018 sym->usl.spillLoc->aop = NULL;
1020 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1021 __FUNCTION__,__LINE__,
1022 sym->usl.spillLoc->rname,
1023 sym->rname, sym->usl.spillLoc->offset);
1025 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1026 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1027 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1029 sym->usl.spillLoc->offset, op);
1030 aop->size = getSize(sym->type);
1036 sym_link *type = operandType(op);
1038 if(IS_PTR_CONST(type))
1040 if(IS_CODEPTR(type))
1042 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1045 /* must be in a register */
1046 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1047 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1048 aop->size = sym->nRegs;
1049 for ( i = 0 ; i < sym->nRegs ;i++)
1050 aop->aopu.aop_reg[i] = sym->regs[i];
1053 /*-----------------------------------------------------------------*/
1054 /* pic16_freeAsmop - free up the asmop given to an operand */
1055 /*----------------------------------------------------------------*/
1056 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1073 /* depending on the asmop type only three cases need work AOP_RO
1074 , AOP_R1 && AOP_STK */
1076 switch (aop->type) {
1080 pic16_emitcode ("pop","ar0");
1084 bitVectUnSetBit(ic->rUsed,R0_IDX);
1090 pic16_emitcode ("pop","ar1");
1094 bitVectUnSetBit(ic->rUsed,R1_IDX);
1100 int stk = aop->aopu.aop_stk + aop->size;
1101 bitVectUnSetBit(ic->rUsed,R0_IDX);
1102 bitVectUnSetBit(ic->rUsed,R1_IDX);
1104 getFreePtr(ic,&aop,FALSE);
1106 if (options.stack10bit)
1108 /* I'm not sure what to do here yet... */
1111 "*** Warning: probably generating bad code for "
1112 "10 bit stack mode.\n");
1116 pic16_emitcode ("mov","a,_bp");
1117 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1118 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1120 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1124 pic16_emitcode("pop","acc");
1125 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1127 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1130 pic16_freeAsmop(op,NULL,ic,TRUE);
1132 pic16_emitcode("pop","ar0");
1137 pic16_emitcode("pop","ar1");
1145 /* all other cases just dealloc */
1149 OP_SYMBOL(op)->aop = NULL;
1150 /* if the symbol has a spill */
1152 SPIL_LOC(op)->aop = NULL;
1157 /*-----------------------------------------------------------------*/
1158 /* pic16_aopGet - for fetching value of the aop */
1159 /*-----------------------------------------------------------------*/
1160 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1165 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1167 /* offset is greater than size then zero */
1168 if (offset > (aop->size - 1) &&
1169 aop->type != AOP_LIT)
1172 /* depending on type */
1173 switch (aop->type) {
1177 sprintf (s,"%s",aop->aopu.aop_immd);
1180 sprintf(s,"(%s >> %d)",
1185 aop->aopu.aop_immd);
1186 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1187 rs = Safe_calloc(1,strlen(s)+1);
1193 sprintf(s,"(%s + %d)",
1196 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1198 sprintf(s,"%s",aop->aopu.aop_dir);
1199 rs = Safe_calloc(1,strlen(s)+1);
1205 // return aop->aopu.aop_reg[offset]->dname;
1207 return aop->aopu.aop_reg[offset]->name;
1210 //pic16_emitcode(";","%d",__LINE__);
1211 return aop->aopu.aop_dir;
1214 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1215 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1217 return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1220 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1221 rs = Safe_calloc(1,strlen(s)+1);
1226 aop->coff = offset ;
1227 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1230 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1232 return aop->aopu.aop_str[offset];
1236 pCodeOp *pcop = aop->aopu.pcop;
1237 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1239 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1240 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1241 sprintf(s,"%s", pcop->name);
1243 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1246 rs = Safe_calloc(1,strlen(s)+1);
1252 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1253 "aopget got unsupported aop->type");
1258 /*-----------------------------------------------------------------*/
1259 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1260 /*-----------------------------------------------------------------*/
1261 pCodeOp *pic16_popGetTempReg(void)
1266 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1271 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1272 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1273 PCOR(pcop)->r->wasUsed=1;
1274 PCOR(pcop)->r->isFree=0;
1276 /* push value on stack */
1277 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1285 /*-----------------------------------------------------------------*/
1286 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1287 /*-----------------------------------------------------------------*/
1288 void pic16_popReleaseTempReg(pCodeOp *pcop)
1290 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1292 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1293 PCOR(pcop)->r->isFree = 1;
1295 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1298 /*-----------------------------------------------------------------*/
1299 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1300 /*-----------------------------------------------------------------*/
1301 pCodeOp *pic16_popGetLabel(unsigned int key)
1304 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1309 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1312 /*-----------------------------------------------------------------*/
1313 /* pic16_popCopyReg - copy a pcode operator */
1314 /*-----------------------------------------------------------------*/
1315 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1319 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1320 pcor->pcop.type = pc->pcop.type;
1322 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1323 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1325 pcor->pcop.name = NULL;
1328 pcor->rIdx = pc->rIdx;
1331 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1336 /*-----------------------------------------------------------------*/
1337 /* pic16_popGetLit - asm operator to pcode operator conversion */
1338 /*-----------------------------------------------------------------*/
1339 pCodeOp *pic16_popGetLit(unsigned int lit)
1341 return pic16_newpCodeOpLit(lit);
1344 /*-----------------------------------------------------------------*/
1345 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1346 /*-----------------------------------------------------------------*/
1347 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1349 return pic16_newpCodeOpLit2(lit, arg2);
1353 /*-----------------------------------------------------------------*/
1354 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1355 /*-----------------------------------------------------------------*/
1356 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1358 return pic16_newpCodeOpImmd(name, offset,index, 0);
1362 /*-----------------------------------------------------------------*/
1363 /* pic16_popGet - asm operator to pcode operator conversion */
1364 /*-----------------------------------------------------------------*/
1365 pCodeOp *pic16_popGetWithString(char *str)
1371 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1375 pcop = pic16_newpCodeOp(str,PO_STR);
1380 /*-----------------------------------------------------------------*/
1381 /* pic16_popRegFromString - */
1382 /*-----------------------------------------------------------------*/
1383 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1386 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1387 pcop->type = PO_DIR;
1389 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1390 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1395 pcop->name = Safe_calloc(1,strlen(str)+1);
1396 strcpy(pcop->name,str);
1398 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1400 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1401 if(PCOR(pcop)->r == NULL) {
1402 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1403 // __FUNCTION__, __LINE__, str, size, offset);
1404 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1406 //fprintf(stderr, "allocating new register -> %s\n", str);
1408 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1410 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d",__LINE__,pcop->name,size,offset);
1412 PCOR(pcop)->instance = offset;
1417 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1421 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1423 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1424 PCOR(pcop)->rIdx = rIdx;
1425 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1426 PCOR(pcop)->r->isFree = 0;
1427 PCOR(pcop)->r->wasUsed = 1;
1429 pcop->type = PCOR(pcop)->r->pc_type;
1434 /*---------------------------------------------------------------------------------*/
1435 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1437 /*---------------------------------------------------------------------------------*/
1438 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1443 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1445 /* comment the following check, so errors to throw up */
1446 // if(!pcop2)return NULL;
1448 temp = pic16_popGet(aop_dst, offset);
1449 pcop2->pcop2 = temp;
1456 /*--------------------------------------------------------------------------------.-*/
1457 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1458 /* VR 030601 , adapted by Hans Dorn */
1459 /*--------------------------------------------------------------------------------.-*/
1460 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1464 pcop2 = (pCodeOpReg2 *)src;
1472 /*---------------------------------------------------------------------------------*/
1473 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1474 /* movff instruction */
1475 /*---------------------------------------------------------------------------------*/
1476 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1481 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1482 pcop2->pcop2 = pic16_popCopyReg(dst);
1484 /* the pCodeOp may be already allocated */
1485 pcop2 = (pCodeOpReg2 *)(src);
1486 pcop2->pcop2 = (pCodeOp *)(dst);
1493 /*-----------------------------------------------------------------*/
1494 /* pic16_popGet - asm operator to pcode operator conversion */
1495 /*-----------------------------------------------------------------*/
1496 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1498 //char *s = buffer ;
1502 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1503 /* offset is greater than
1506 // if (offset > (aop->size - 1) &&
1507 // aop->type != AOP_LIT)
1508 // return NULL; //zero;
1510 /* depending on type */
1511 switch (aop->type) {
1517 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1518 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1525 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1526 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1530 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1532 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1534 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1536 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1537 PCOR(pcop)->rIdx = rIdx;
1538 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1539 PCOR(pcop)->r->wasUsed=1;
1540 PCOR(pcop)->r->isFree=0;
1542 PCOR(pcop)->instance = offset;
1543 pcop->type = PCOR(pcop)->r->pc_type;
1544 // rs = aop->aopu.aop_reg[offset]->name;
1545 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1549 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1550 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1556 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1557 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1561 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1563 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1565 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1566 PCOR(pcop)->rIdx = rIdx;
1567 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1568 PCOR(pcop)->r->wasUsed=1;
1569 PCOR(pcop)->r->isFree=0;
1571 PCOR(pcop)->instance = offset;
1572 pcop->type = PCOR(pcop)->r->pc_type;
1573 rs = aop->aopu.aop_reg[offset]->name;
1574 DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1579 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1581 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1582 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1583 //if(PCOR(pcop)->r == NULL)
1584 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1588 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1589 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1592 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1593 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1596 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1597 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1598 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1599 pcop->type = PCOR(pcop)->r->pc_type;
1600 pcop->name = PCOR(pcop)->r->name;
1606 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1608 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1609 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1611 switch( aop->aopu.pcop->type ) {
1612 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1613 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1615 assert( 0 ); /* should never reach here */;
1618 PCOI(pcop)->offset = offset;
1623 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1624 "pic16_popGet got unsupported aop->type");
1627 /*-----------------------------------------------------------------*/
1628 /* pic16_aopPut - puts a string for a aop */
1629 /*-----------------------------------------------------------------*/
1630 void pic16_aopPut (asmop *aop, char *s, int offset)
1635 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1637 if (aop->size && offset > ( aop->size - 1)) {
1638 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1639 "pic16_aopPut got offset > aop->size");
1643 /* will assign value to value */
1644 /* depending on where it is ofcourse */
1645 switch (aop->type) {
1648 sprintf(d,"(%s + %d)",
1649 aop->aopu.aop_dir,offset);
1650 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1653 sprintf(d,"%s",aop->aopu.aop_dir);
1656 DEBUGpic16_emitcode(";","%d",__LINE__);
1658 pic16_emitcode("movf","%s,w",s);
1659 pic16_emitcode("movwf","%s",d);
1662 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1663 if(offset >= aop->size) {
1664 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1667 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1670 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1677 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1678 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1681 strcmp(s,"r0") == 0 ||
1682 strcmp(s,"r1") == 0 ||
1683 strcmp(s,"r2") == 0 ||
1684 strcmp(s,"r3") == 0 ||
1685 strcmp(s,"r4") == 0 ||
1686 strcmp(s,"r5") == 0 ||
1687 strcmp(s,"r6") == 0 ||
1688 strcmp(s,"r7") == 0 )
1689 pic16_emitcode("mov","%s,%s ; %d",
1690 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1694 if(strcmp(s,"W")==0 )
1695 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
1697 pic16_emitcode("movwf","%s",
1698 aop->aopu.aop_reg[offset]->name);
1700 if(strcmp(s,zero)==0) {
1701 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1703 } else if(strcmp(s,"W")==0) {
1704 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1705 pcop->type = PO_GPR_REGISTER;
1707 PCOR(pcop)->rIdx = -1;
1708 PCOR(pcop)->r = NULL;
1710 DEBUGpic16_emitcode(";","%d",__LINE__);
1711 pcop->name = Safe_strdup(s);
1712 pic16_emitpcode(POC_MOVFW,pcop);
1713 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1714 } else if(strcmp(s,one)==0) {
1715 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1716 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1718 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1726 if (aop->type == AOP_DPTR2)
1732 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1733 "pic16_aopPut writting to code space");
1737 while (offset > aop->coff) {
1739 pic16_emitcode ("inc","dptr");
1742 while (offset < aop->coff) {
1744 pic16_emitcode("lcall","__decdptr");
1749 /* if not in accumulater */
1752 pic16_emitcode ("movx","@dptr,a");
1754 if (aop->type == AOP_DPTR2)
1762 while (offset > aop->coff) {
1764 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1766 while (offset < aop->coff) {
1768 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1774 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1779 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1781 if (strcmp(s,"r0") == 0 ||
1782 strcmp(s,"r1") == 0 ||
1783 strcmp(s,"r2") == 0 ||
1784 strcmp(s,"r3") == 0 ||
1785 strcmp(s,"r4") == 0 ||
1786 strcmp(s,"r5") == 0 ||
1787 strcmp(s,"r6") == 0 ||
1788 strcmp(s,"r7") == 0 ) {
1790 sprintf(buffer,"a%s",s);
1791 pic16_emitcode("mov","@%s,%s",
1792 aop->aopu.aop_ptr->name,buffer);
1794 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1799 if (strcmp(s,"a") == 0)
1800 pic16_emitcode("push","acc");
1802 pic16_emitcode("push","%s",s);
1807 /* if bit variable */
1808 if (!aop->aopu.aop_dir) {
1809 pic16_emitcode("clr","a");
1810 pic16_emitcode("rlc","a");
1813 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1816 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1819 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1821 lbl = newiTempLabel(NULL);
1823 if (strcmp(s,"a")) {
1826 pic16_emitcode("clr","c");
1827 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1828 pic16_emitcode("cpl","c");
1829 pic16_emitcode("","%05d_DS_:",lbl->key+100);
1830 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1837 if (strcmp(aop->aopu.aop_str[offset],s))
1838 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1843 if (!offset && (strcmp(s,"acc") == 0))
1846 if (strcmp(aop->aopu.aop_str[offset],s))
1847 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1851 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1852 "pic16_aopPut got unsupported aop->type");
1858 /*-----------------------------------------------------------------*/
1859 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1860 /*-----------------------------------------------------------------*/
1861 static void mov2w (asmop *aop, int offset)
1867 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1870 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1872 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1877 /* push pcop into stack */
1878 void pic16_pushpCodeOp(pCodeOp *pcop)
1880 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1881 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1884 /* pop pcop from stack */
1885 void pic16_poppCodeOp(pCodeOp *pcop)
1887 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1891 /*-----------------------------------------------------------------*/
1892 /* pushw - pushes wreg to stack */
1893 /*-----------------------------------------------------------------*/
1896 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1897 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1901 /*-----------------------------------------------------------------*/
1902 /* pushaop - pushes aop to stack */
1903 /*-----------------------------------------------------------------*/
1904 void pushaop(asmop *aop, int offset)
1906 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1907 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1910 /*-----------------------------------------------------------------*/
1911 /* popaop - pops aop from stack */
1912 /*-----------------------------------------------------------------*/
1913 void popaop(asmop *aop, int offset)
1915 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
1916 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1919 void popaopidx(asmop *aop, int offset, int index)
1923 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1925 if(STACK_MODEL_LARGE)ofs++;
1927 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1928 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1931 /*-----------------------------------------------------------------*/
1932 /* reAdjustPreg - points a register back to where it should */
1933 /*-----------------------------------------------------------------*/
1934 static void reAdjustPreg (asmop *aop)
1938 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1940 if ((size = aop->size) <= 1)
1943 switch (aop->type) {
1947 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1951 if (aop->type == AOP_DPTR2)
1957 pic16_emitcode("lcall","__decdptr");
1960 if (aop->type == AOP_DPTR2)
1972 /*-----------------------------------------------------------------*/
1973 /* opIsGptr: returns non-zero if the passed operand is */
1974 /* a generic pointer type. */
1975 /*-----------------------------------------------------------------*/
1976 static int opIsGptr(operand *op)
1978 sym_link *type = operandType(op);
1980 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1981 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1989 /*-----------------------------------------------------------------*/
1990 /* pic16_getDataSize - get the operand data size */
1991 /*-----------------------------------------------------------------*/
1992 int pic16_getDataSize(operand *op)
1994 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1997 return AOP_SIZE(op);
1999 // tsd- in the pic port, the genptr size is 1, so this code here
2000 // fails. ( in the 8051 port, the size was 4).
2003 size = AOP_SIZE(op);
2004 if (size == GPTRSIZE)
2006 sym_link *type = operandType(op);
2007 if (IS_GENPTR(type))
2009 /* generic pointer; arithmetic operations
2010 * should ignore the high byte (pointer type).
2013 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2020 /*-----------------------------------------------------------------*/
2021 /* pic16_outAcc - output Acc */
2022 /*-----------------------------------------------------------------*/
2023 void pic16_outAcc(operand *result)
2026 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2027 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2030 size = pic16_getDataSize(result);
2032 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2035 /* unsigned or positive */
2037 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2042 /*-----------------------------------------------------------------*/
2043 /* pic16_outBitC - output a bit C */
2044 /* Move to result the value of Carry flag -- VR */
2045 /*-----------------------------------------------------------------*/
2046 void pic16_outBitC(operand *result)
2050 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2051 /* if the result is bit */
2052 if (AOP_TYPE(result) == AOP_CRY) {
2053 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2054 pic16_aopPut(AOP(result),"c",0);
2057 i = AOP_SIZE(result);
2059 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2061 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2064 pic16_emitcode("clr","a ; %d", __LINE__);
2065 pic16_emitcode("rlc","a");
2066 pic16_outAcc(result);
2071 /*-----------------------------------------------------------------*/
2072 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2073 /*-----------------------------------------------------------------*/
2074 void pic16_toBoolean(operand *oper)
2076 int size = AOP_SIZE(oper) - 1;
2079 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2081 if ( AOP_TYPE(oper) != AOP_ACC) {
2082 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2085 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2090 #if !defined(GEN_Not)
2091 /*-----------------------------------------------------------------*/
2092 /* genNot - generate code for ! operation */
2093 /*-----------------------------------------------------------------*/
2094 static void pic16_genNot (iCode *ic)
2099 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2100 /* assign asmOps to operand & result */
2101 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2102 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2104 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2105 /* if in bit space then a special case */
2106 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2107 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2108 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2109 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2111 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2112 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2113 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2118 size = AOP_SIZE(IC_LEFT(ic));
2120 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2121 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2122 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2125 pic16_toBoolean(IC_LEFT(ic));
2127 tlbl = newiTempLabel(NULL);
2128 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2129 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2130 pic16_outBitC(IC_RESULT(ic));
2133 /* release the aops */
2134 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2135 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2140 #if !defined(GEN_Cpl)
2141 /*-----------------------------------------------------------------*/
2142 /* genCpl - generate code for complement */
2143 /*-----------------------------------------------------------------*/
2144 static void pic16_genCpl (iCode *ic)
2150 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2151 /* assign asmOps to operand & result */
2152 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2153 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2155 /* if both are in bit space then
2157 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2158 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2160 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2161 pic16_emitcode("cpl","c");
2162 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2166 size = AOP_SIZE(IC_RESULT(ic));
2169 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2171 pic16_emitcode("cpl","a");
2172 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2174 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2175 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2177 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2178 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2186 /* release the aops */
2187 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2188 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2192 /*-----------------------------------------------------------------*/
2193 /* genUminusFloat - unary minus for floating points */
2194 /*-----------------------------------------------------------------*/
2195 static void genUminusFloat(operand *op,operand *result)
2197 int size ,offset =0 ;
2200 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2201 /* for this we just need to flip the
2202 first it then copy the rest in place */
2203 size = AOP_SIZE(op) - 1;
2204 l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2208 pic16_emitcode("cpl","acc.7");
2209 pic16_aopPut(AOP(result),"a",3);
2212 pic16_aopPut(AOP(result),
2213 pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2219 /*-----------------------------------------------------------------*/
2220 /* genUminus - unary minus code generation */
2221 /*-----------------------------------------------------------------*/
2222 static void genUminus (iCode *ic)
2225 sym_link *optype, *rtype;
2227 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2230 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2231 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2233 /* if both in bit space then special case */
2234 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2235 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2237 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2238 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2239 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2244 optype = operandType(IC_LEFT(ic));
2245 rtype = operandType(IC_RESULT(ic));
2247 /* if float then do float stuff */
2248 if (IS_FLOAT(optype)) {
2249 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2253 /* otherwise subtract from zero by taking the 2's complement */
2254 size = AOP_SIZE(IC_LEFT(ic));
2256 for(i=0; i<size; i++) {
2257 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2258 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)),i));
2260 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2261 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2265 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2266 for(i=1; i<size; i++) {
2268 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2272 /* release the aops */
2273 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2274 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2277 /*-----------------------------------------------------------------*/
2278 /* saveRegisters - will look for a call and save the registers */
2279 /*-----------------------------------------------------------------*/
2280 static void saveRegisters(iCode *lic)
2287 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2289 for (ic = lic ; ic ; ic = ic->next)
2290 if (ic->op == CALL || ic->op == PCALL)
2294 fprintf(stderr,"found parameter push with no function call\n");
2298 /* if the registers have been saved already then
2300 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2303 /* find the registers in use at this time
2304 and push them away to safety */
2305 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2309 if (options.useXstack) {
2310 if (bitVectBitValue(rsave,R0_IDX))
2311 pic16_emitcode("mov","b,r0");
2312 pic16_emitcode("mov","r0,%s",spname);
2313 for (i = 0 ; i < pic16_nRegs ; i++) {
2314 if (bitVectBitValue(rsave,i)) {
2316 pic16_emitcode("mov","a,b");
2318 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2319 pic16_emitcode("movx","@r0,a");
2320 pic16_emitcode("inc","r0");
2323 pic16_emitcode("mov","%s,r0",spname);
2324 if (bitVectBitValue(rsave,R0_IDX))
2325 pic16_emitcode("mov","r0,b");
2327 //for (i = 0 ; i < pic16_nRegs ; i++) {
2328 // if (bitVectBitValue(rsave,i))
2329 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2332 dtype = operandType(IC_LEFT(ic));
2333 if (currFunc && dtype &&
2334 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2335 IFFUNC_ISISR(currFunc->type) &&
2338 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2341 /*-----------------------------------------------------------------*/
2342 /* unsaveRegisters - pop the pushed registers */
2343 /*-----------------------------------------------------------------*/
2344 static void unsaveRegisters (iCode *ic)
2349 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2350 /* find the registers in use at this time
2351 and push them away to safety */
2352 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2355 if (options.useXstack) {
2356 pic16_emitcode("mov","r0,%s",spname);
2357 for (i = pic16_nRegs ; i >= 0 ; i--) {
2358 if (bitVectBitValue(rsave,i)) {
2359 pic16_emitcode("dec","r0");
2360 pic16_emitcode("movx","a,@r0");
2362 pic16_emitcode("mov","b,a");
2364 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2368 pic16_emitcode("mov","%s,r0",spname);
2369 if (bitVectBitValue(rsave,R0_IDX))
2370 pic16_emitcode("mov","r0,b");
2372 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2373 // if (bitVectBitValue(rsave,i))
2374 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2380 /*-----------------------------------------------------------------*/
2382 /*-----------------------------------------------------------------*/
2383 static void pushSide(operand * oper, int size)
2386 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2388 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2389 if (AOP_TYPE(oper) != AOP_REG &&
2390 AOP_TYPE(oper) != AOP_DIR &&
2392 pic16_emitcode("mov","a,%s",l);
2393 pic16_emitcode("push","acc");
2395 pic16_emitcode("push","%s",l);
2400 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2402 // (AOP(left)->aopu.pcop->type == PO_DIR)?
2404 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2405 pic16_emitpcode(POC_MOVFW, src);
2406 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2408 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2409 src, pic16_popGet(AOP(op), offset)));
2414 /*-----------------------------------------------------------------*/
2415 /* assignResultValue - assign results to oper, rescall==1 is */
2416 /* called from genCall() or genPCall() */
2417 /*-----------------------------------------------------------------*/
2418 static void assignResultValue(operand * oper, int rescall)
2420 int size = AOP_SIZE(oper);
2422 DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2423 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2426 /* assign result from a call/pcall function() */
2428 /* function results are stored in a special order,
2429 * see top of file with Function return policy, or manual */
2432 /* 8-bits, result in WREG */
2433 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2436 /* 16-bits, result in PRODL:WREG */
2437 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2441 /* 24-bits, result in PRODH:PRODL:WREG */
2442 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2446 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2447 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2450 /* >32-bits, result on stack, and FSR0 points to beginning.
2451 * Fix stack when done */
2454 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2455 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2457 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2462 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2463 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2464 if(STACK_MODEL_LARGE) {
2466 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2470 if(!GpsuedoStkPtr) {
2471 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2472 /* The last byte in the assignment is in W */
2474 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2479 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2480 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2482 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2488 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2490 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2500 /*-----------------------------------------------------------------*/
2501 /* genIpush - genrate code for pushing this gets a little complex */
2502 /*-----------------------------------------------------------------*/
2503 static void genIpush (iCode *ic)
2506 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2508 int size, offset = 0 ;
2512 /* if this is not a parm push : ie. it is spill push
2513 and spill push is always done on the local stack */
2514 if (!ic->parmPush) {
2516 /* and the item is spilt then do nothing */
2517 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2520 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2521 size = AOP_SIZE(IC_LEFT(ic));
2522 /* push it on the stack */
2524 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2529 pic16_emitcode("push","%s",l);
2534 /* this is a paramter push: in this case we call
2535 the routine to find the call and save those
2536 registers that need to be saved */
2539 /* then do the push */
2540 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2543 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2544 size = AOP_SIZE(IC_LEFT(ic));
2547 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2548 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2549 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2551 pic16_emitcode("mov","a,%s",l);
2552 pic16_emitcode("push","acc");
2554 pic16_emitcode("push","%s",l);
2557 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2561 /*-----------------------------------------------------------------*/
2562 /* genIpop - recover the registers: can happen only for spilling */
2563 /*-----------------------------------------------------------------*/
2564 static void genIpop (iCode *ic)
2566 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2571 /* if the temp was not pushed then */
2572 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2575 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2576 size = AOP_SIZE(IC_LEFT(ic));
2579 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2582 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2586 /*-----------------------------------------------------------------*/
2587 /* unsaverbank - restores the resgister bank from stack */
2588 /*-----------------------------------------------------------------*/
2589 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2591 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2597 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2599 if (options.useXstack) {
2601 r = getFreePtr(ic,&aop,FALSE);
2604 pic16_emitcode("mov","%s,_spx",r->name);
2605 pic16_emitcode("movx","a,@%s",r->name);
2606 pic16_emitcode("mov","psw,a");
2607 pic16_emitcode("dec","%s",r->name);
2610 pic16_emitcode ("pop","psw");
2613 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2614 if (options.useXstack) {
2615 pic16_emitcode("movx","a,@%s",r->name);
2616 //pic16_emitcode("mov","(%s+%d),a",
2617 // regspic16[i].base,8*bank+regspic16[i].offset);
2618 pic16_emitcode("dec","%s",r->name);
2621 pic16_emitcode("pop",""); //"(%s+%d)",
2622 //regspic16[i].base,8*bank); //+regspic16[i].offset);
2625 if (options.useXstack) {
2627 pic16_emitcode("mov","_spx,%s",r->name);
2628 pic16_freeAsmop(NULL,aop,ic,TRUE);
2634 /*-----------------------------------------------------------------*/
2635 /* saverbank - saves an entire register bank on the stack */
2636 /*-----------------------------------------------------------------*/
2637 static void saverbank (int bank, iCode *ic, bool pushPsw)
2639 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2645 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2646 if (options.useXstack) {
2649 r = getFreePtr(ic,&aop,FALSE);
2650 pic16_emitcode("mov","%s,_spx",r->name);
2654 for (i = 0 ; i < pic16_nRegs ;i++) {
2655 if (options.useXstack) {
2656 pic16_emitcode("inc","%s",r->name);
2657 //pic16_emitcode("mov","a,(%s+%d)",
2658 // regspic16[i].base,8*bank+regspic16[i].offset);
2659 pic16_emitcode("movx","@%s,a",r->name);
2661 pic16_emitcode("push","");// "(%s+%d)",
2662 //regspic16[i].base,8*bank+regspic16[i].offset);
2666 if (options.useXstack) {
2667 pic16_emitcode("mov","a,psw");
2668 pic16_emitcode("movx","@%s,a",r->name);
2669 pic16_emitcode("inc","%s",r->name);
2670 pic16_emitcode("mov","_spx,%s",r->name);
2671 pic16_freeAsmop (NULL,aop,ic,TRUE);
2674 pic16_emitcode("push","psw");
2676 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2684 /*-----------------------------------------------------------------*/
2685 /* genCall - generates a call statement */
2686 /*-----------------------------------------------------------------*/
2687 static void genCall (iCode *ic)
2692 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2694 /* if caller saves & we have not saved then */
2698 /* if we are calling a function that is not using
2699 * the same register bank then we need to save the
2700 * destination registers on the stack */
2701 dtype = operandType(IC_LEFT(ic));
2702 if (currFunc && dtype &&
2703 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2704 IFFUNC_ISISR(currFunc->type) &&
2707 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2709 /* if send set is not empty the assign */
2713 /* For the Pic port, there is no data stack.
2714 * So parameters passed to functions are stored
2715 * in registers. (The pCode optimizer will get
2716 * rid of most of these :). */
2718 int psuedoStkPtr=-1;
2719 int firstTimeThruLoop = 1;
2721 _G.sendSet = reverseSet(_G.sendSet);
2723 /* First figure how many parameters are getting passed */
2724 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2725 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2726 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2727 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2730 stackParms = psuedoStkPtr;
2732 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2733 int size, offset = 0;
2735 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2736 size = AOP_SIZE(IC_LEFT(sic));
2739 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2740 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2741 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2743 if(!firstTimeThruLoop) {
2744 /* If this is not the first time we've been through the loop
2745 * then we need to save the parameter in a temporary
2746 * register. The last byte of the last parameter is
2750 --psuedoStkPtr; // sanity check
2753 firstTimeThruLoop=0;
2755 mov2w (AOP(IC_LEFT(sic)), offset);
2758 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2764 pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2765 OP_SYMBOL(IC_LEFT(ic))->rname :
2766 OP_SYMBOL(IC_LEFT(ic))->name));
2769 /* if we need assign a result value */
2770 if ((IS_ITEMP(IC_RESULT(ic)) &&
2771 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2772 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2773 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2776 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2779 assignResultValue(IC_RESULT(ic), 1);
2781 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2782 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2784 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2788 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2789 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2790 if(STACK_MODEL_LARGE) {
2792 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2796 /* adjust the stack for parameters if required */
2797 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2799 if (ic->parmBytes) {
2802 if (ic->parmBytes > 3) {
2803 pic16_emitcode("mov","a,%s",spname);
2804 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2805 pic16_emitcode("mov","%s,a",spname);
2807 for ( i = 0 ; i < ic->parmBytes ;i++)
2808 pic16_emitcode("dec","%s",spname);
2812 /* if register bank was saved then pop them */
2814 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2816 /* if we hade saved some registers then unsave them */
2817 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2818 unsaveRegisters (ic);
2824 /*-----------------------------------------------------------------*/ // patch 14
2825 /* genPcall - generates a call by pointer statement */
2826 /*-----------------------------------------------------------------*/
2828 // new version, created from genCall
2830 static void genPcall (iCode *ic)
2834 symbol *retlbl = newiTempLabel(NULL);
2835 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2837 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2839 /* if caller saves & we have not saved then */
2843 /* if we are calling a function that is not using
2844 * the same register bank then we need to save the
2845 * destination registers on the stack */
2846 dtype = operandType(IC_LEFT(ic));
2847 if (currFunc && dtype &&
2848 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2849 IFFUNC_ISISR(currFunc->type) &&
2852 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2854 /* if send set is not empty the assign */
2858 /* For the Pic port, there is no data stack.
2859 * So parameters passed to functions are stored
2860 * in registers. (The pCode optimizer will get
2861 * rid of most of these :). */
2863 int psuedoStkPtr=-1;
2864 int firstTimeThruLoop = 1;
2866 _G.sendSet = reverseSet(_G.sendSet);
2868 /* First figure how many parameters are getting passed */
2869 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2870 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2871 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2872 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2875 stackParms = psuedoStkPtr;
2877 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2878 int size, offset = 0;
2880 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2881 size = AOP_SIZE(IC_LEFT(sic));
2884 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2885 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2886 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2888 if(!firstTimeThruLoop) {
2889 /* If this is not the first time we've been through the loop
2890 * then we need to save the parameter in a temporary
2891 * register. The last byte of the last parameter is
2895 --psuedoStkPtr; // sanity check
2898 firstTimeThruLoop=0;
2900 mov2w (AOP(IC_LEFT(sic)), offset);
2903 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2908 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2910 // push return address
2911 // push $ on return stack, then replace with retlbl
2913 pic16_emitpcodeNULLop(POC_PUSH);
2915 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2916 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2917 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2918 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2919 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2920 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2922 /* make the call by writing the pointer into pc */
2923 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
2924 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
2926 // note: MOVFF to PCL not allowed
2927 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
2928 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2931 // pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key));
2932 // pic16_emitpcodeNULLop(POC_NOP);
2933 // pic16_emitpcodeNULLop(POC_NOP);
2935 /* return address is here: (X) */
2936 pic16_emitpLabelFORCE(retlbl->key);
2938 // pic16_emitpcodeNULLop(POC_NOP);
2940 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2943 /* if we need assign a result value */
2944 if ((IS_ITEMP(IC_RESULT(ic)) &&
2945 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2946 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2947 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2950 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2953 assignResultValue(IC_RESULT(ic), 1);
2955 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2956 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2958 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2962 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2963 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2964 if(STACK_MODEL_LARGE) {
2966 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2970 /* adjust the stack for parameters if required */
2971 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2973 if (ic->parmBytes) {
2976 if (ic->parmBytes > 3) {
2977 pic16_emitcode("mov","a,%s",spname);
2978 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2979 pic16_emitcode("mov","%s,a",spname);
2981 for ( i = 0 ; i < ic->parmBytes ;i++)
2982 pic16_emitcode("dec","%s",spname);
2985 /* if register bank was saved then pop them */
2987 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2989 /* if we hade saved some registers then unsave them */
2990 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2991 unsaveRegisters (ic);
2996 // old version, kept for reference
2998 /*-----------------------------------------------------------------*/
2999 /* genPcall - generates a call by pointer statement */
3000 /*-----------------------------------------------------------------*/
3001 static void genPcall (iCode *ic)
3004 symbol *rlbl = newiTempLabel(NULL);
3007 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3008 /* if caller saves & we have not saved then */
3012 /* if we are calling a function that is not using
3013 the same register bank then we need to save the
3014 destination registers on the stack */
3015 dtype = operandType(IC_LEFT(ic));
3016 if (currFunc && dtype &&
3017 IFFUNC_ISISR(currFunc->type) &&
3018 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3019 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3022 /* push the return address on to the stack */
3023 pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3024 pic16_emitcode("push","acc");
3025 pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3026 pic16_emitcode("push","acc");
3028 if (options.model == MODEL_FLAT24)
3030 pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3031 pic16_emitcode("push","acc");
3034 /* now push the calling address */
3035 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3037 pushSide(IC_LEFT(ic), FPTRSIZE);
3039 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3041 /* if send set is not empty the assign */
3045 for (sic = setFirstItem(_G.sendSet) ; sic ;
3046 sic = setNextItem(_G.sendSet)) {
3047 int size, offset = 0;
3048 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3049 size = AOP_SIZE(IC_LEFT(sic));
3051 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3053 if (strcmp(l,fReturn[offset]))
3054 pic16_emitcode("mov","%s,%s",
3059 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3064 pic16_emitcode("ret","");
3065 pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3068 /* if we need assign a result value */
3069 if ((IS_ITEMP(IC_RESULT(ic)) &&
3070 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3071 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3072 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3075 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3078 assignResultValue(IC_RESULT(ic), 1);
3080 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3083 /* adjust the stack for parameters if
3085 if (ic->parmBytes) {
3087 if (ic->parmBytes > 3) {
3088 pic16_emitcode("mov","a,%s",spname);
3089 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3090 pic16_emitcode("mov","%s,a",spname);
3092 for ( i = 0 ; i < ic->parmBytes ;i++)
3093 pic16_emitcode("dec","%s",spname);
3097 /* if register bank was saved then unsave them */
3098 if (currFunc && dtype &&
3099 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3100 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3102 /* if we hade saved some registers then
3105 unsaveRegisters (ic);
3111 /*-----------------------------------------------------------------*/
3112 /* resultRemat - result is rematerializable */
3113 /*-----------------------------------------------------------------*/
3114 static int resultRemat (iCode *ic)
3116 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3117 if (SKIP_IC(ic) || ic->op == IFX)
3120 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3121 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3122 if (sym->remat && !POINTER_SET(ic))
3129 #if defined(__BORLANDC__) || defined(_MSC_VER)
3130 #define STRCASECMP stricmp
3132 #define STRCASECMP strcasecmp
3136 /*-----------------------------------------------------------------*/
3137 /* inExcludeList - return 1 if the string is in exclude Reg list */
3138 /*-----------------------------------------------------------------*/
3139 static bool inExcludeList(char *s)
3141 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3144 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3145 if (options.excludeRegs[i] &&
3146 STRCASECMP(options.excludeRegs[i],"none") == 0)
3149 for ( i = 0 ; options.excludeRegs[i]; i++) {
3150 if (options.excludeRegs[i] &&
3151 STRCASECMP(s,options.excludeRegs[i]) == 0)
3158 /*-----------------------------------------------------------------*/
3159 /* genFunction - generated code for function entry */
3160 /*-----------------------------------------------------------------*/
3161 static void genFunction (iCode *ic)
3166 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3168 pic16_labelOffset += (max_key+4);
3173 ftype = operandType(IC_LEFT(ic));
3174 sym = OP_SYMBOL(IC_LEFT(ic));
3176 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3177 /* create an absolute section at the interrupt vector:
3178 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3186 sym = OP_SYMBOL( IC_LEFT(ic));
3188 if(interrupts[i]->name
3189 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3196 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3197 __FILE__, __LINE__, sym->name);
3200 _G.interruptvector = found;
3203 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3204 asym = newSymbol(asymname, 0);
3206 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3207 pic16_addpBlock( apb );
3209 pic16_addpCode2pBlock(apb,
3210 pic16_newpCodeCharP(";-----------------------------------------"));
3213 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3215 pic16_addpCode2pBlock(apb,
3216 pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3218 /* mark the end of this tiny function */
3219 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3224 abSym = Safe_calloc(1, sizeof(absSym));
3225 abSym->name = Safe_strdup( asymname );
3227 switch( _G.interruptvector ) {
3228 case 0: abSym->address = 0x000000; break;
3229 case 1: abSym->address = 0x000008; break;
3230 case 2: abSym->address = 0x000018; break;
3233 /* relocate interrupt vectors if needed */
3234 abSym->address += pic16_options.ivt_loc;
3236 addSet(&absSymSet, abSym);
3241 /* create the function header */
3242 pic16_emitcode(";","-----------------------------------------");
3243 pic16_emitcode(";"," function %s",sym->name);
3244 pic16_emitcode(";","-----------------------------------------");
3246 pic16_emitcode("","%s:",sym->rname);
3247 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3253 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3254 if(!strcmp(ab->name, sym->name)) {
3255 pic16_pBlockConvert2Absolute(pb);
3262 if(IFFUNC_ISNAKED(ftype)) {
3263 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3267 /* if critical function then turn interrupts off */
3268 if (IFFUNC_ISCRITICAL(ftype))
3269 pic16_emitcode("clr","ea");
3271 /* if this is an interrupt service routine then
3272 * save acc, b, dpl, dph */
3273 if (IFFUNC_ISISR(sym->type)) {
3275 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3276 if(!(_G.interruptvector == 1)) {
3278 /* do not save WREG,STATUS,BSR for high priority interrupts
3279 * because they are stored in the hardware shadow registers already */
3281 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3282 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3283 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3286 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3287 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3288 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3289 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3291 // pic16_pBlockConvert2ISR(pb);
3293 /* if any registers used */
3294 if (sym->regsUsed) {
3295 /* save the registers used */
3296 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3297 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3298 if (bitVectBitValue(sym->regsUsed,i)) {
3299 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3300 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3301 // pic16_regWithIdx(i)->name);
3303 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3309 /* emit code to setup stack frame if user enabled,
3310 * and function is not main() */
3312 // fprintf(stderr, "function name: %s\n", sym->name);
3313 if(strcmp(sym->name, "main")) {
3314 if(/*!options.ommitFramePtr || */sym->regsUsed) {
3315 /* setup the stack frame */
3316 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3317 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3318 if(STACK_MODEL_LARGE)
3319 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3323 /* if callee-save to be used for this function
3324 * then save the registers being used in this function */
3325 // if (IFFUNC_CALLEESAVES(sym->type))
3329 // fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3331 // pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3333 /* if any registers used */
3334 if (sym->regsUsed) {
3335 /* save the registers used */
3336 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3337 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3338 if (bitVectBitValue(sym->regsUsed,i)) {
3340 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3341 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3342 // pic16_regWithIdx(i)->name);
3344 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3346 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3347 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3348 // &pic16_pc_postdec1, 0));
3360 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3362 if (options.useXstack) {
3363 pic16_emitcode("mov","r0,%s",spname);
3364 pic16_emitcode("mov","a,_bp");
3365 pic16_emitcode("movx","@r0,a");
3366 pic16_emitcode("inc","%s",spname);
3368 /* set up the stack */
3369 pic16_emitcode ("push","_bp"); /* save the callers stack */
3371 pic16_emitcode ("mov","_bp,%s",spname);
3374 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3376 /* adjust the stack for the function */
3381 werror(W_STACK_OVERFLOW,sym->name);
3383 if (i > 3 && sym->recvSize < 4) {
3384 pic16_emitcode ("mov","a,sp");
3385 pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3386 pic16_emitcode ("mov","sp,a");
3389 pic16_emitcode("inc","sp");
3393 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3395 pic16_emitcode ("mov","a,_spx");
3396 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3397 pic16_emitcode ("mov","_spx,a");
3402 /*-----------------------------------------------------------------*/
3403 /* genEndFunction - generates epilogue for functions */
3404 /*-----------------------------------------------------------------*/
3405 static void genEndFunction (iCode *ic)
3407 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3409 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3411 if(IFFUNC_ISNAKED(sym->type)) {
3412 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3417 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3419 pic16_emitcode ("mov","%s,_bp",spname);
3423 /* if use external stack but some variables were
3424 added to the local stack then decrement the
3426 if (options.useXstack && sym->stack) {
3427 pic16_emitcode("mov","a,sp");
3428 pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3429 pic16_emitcode("mov","sp,a");
3434 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3435 if (options.useXstack) {
3436 pic16_emitcode("mov","r0,%s",spname);
3437 pic16_emitcode("movx","a,@r0");
3438 pic16_emitcode("mov","_bp,a");
3439 pic16_emitcode("dec","%s",spname);
3443 pic16_emitcode ("pop","_bp");
3448 if (IFFUNC_ISISR(sym->type)) {
3449 /* now we need to restore the registers */
3450 /* if any registers used */
3451 if (sym->regsUsed) {
3454 /* restore registers used */
3455 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3456 for ( i = sym->regsUsed->size; i >= 0; i--) {
3457 if (bitVectBitValue(sym->regsUsed,i)) {
3459 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3460 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3461 // pic16_regWithIdx(i)->name);
3463 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3465 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3466 // &pic16_pc_preinc1,
3467 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3473 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3474 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3475 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3476 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3478 if(!(_G.interruptvector == 1)) {
3479 /* do not restore interrupt vector for WREG,STATUS,BSR
3480 * for high priority interrupt, see genFunction */
3482 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3483 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3484 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3487 _G.interruptvector = 0; /* sanity check */
3489 // pic16_pBlockConvert2ISR(pb);
3492 /* if debug then send end of function */
3493 /* if (options.debug && currFunc) */
3495 debugFile->writeEndFunction (currFunc, ic, 1);
3498 pic16_emitpcodeNULLop(POC_RETFIE);
3500 if (IFFUNC_ISCRITICAL(sym->type))
3501 pic16_emitcode("setb","ea");
3504 // pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3506 /* if any registers used */
3507 if (sym->regsUsed) {
3509 /* save the 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));
3529 // pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3530 /* if debug then send end of function */
3532 debugFile->writeEndFunction (currFunc, ic, 1);
3535 /* insert code to restore stack frame, if user enabled it
3536 * and function is not main() */
3539 if(strcmp(sym->name, "main")) {
3540 if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3541 /* restore stack frame */
3542 if(STACK_MODEL_LARGE)
3543 pic16_emitpcode(POC_MOVFF,
3544 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3545 pic16_emitpcode(POC_MOVFF,
3546 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3550 pic16_emitcode ("return","");
3551 pic16_emitpcodeNULLop(POC_RETURN);
3553 /* Mark the end of a function */
3554 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3560 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3564 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3566 if(dest->type != PO_WREG)
3567 pic16_emitpcode(POC_MOVWF, dest);
3569 if(dest->type == PO_WREG && (offset == 0)) {
3570 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3574 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3575 pic16_popGet(AOP(op), offset), dest));
3579 /*-----------------------------------------------------------------*/
3580 /* genRet - generate code for return statement */
3581 /*-----------------------------------------------------------------*/
3582 static void genRet (iCode *ic)
3587 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3588 /* if we have no return value then
3589 * just generate the "ret" */
3594 /* we have something to return then
3595 * move the return value into place */
3596 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3597 size = AOP_SIZE(IC_LEFT(ic));
3601 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3602 // pic16_emitpcode(POC_MOVFF,
3603 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3606 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3607 // pic16_emitpcode(POC_MOVFF,
3608 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3611 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3612 // pic16_emitpcode(POC_MOVFF,
3613 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3616 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3618 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3619 // pic16_emitpcode(POC_MOVFF,
3620 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3623 /* >32-bits, setup stack and FSR0 */
3625 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3626 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3628 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3630 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3635 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3636 pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3638 if(STACK_MODEL_LARGE) {
3639 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3640 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3642 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3647 /* old code, left here for reference -- VR */
3651 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3653 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3654 pic16_emitpcomment("push %s",l);
3657 DEBUGpic16_emitcode(";", "%d", __LINE__);
3658 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3659 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3661 if (strcmp(fReturn[offset],l)) {
3662 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3663 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3664 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3666 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3670 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3680 if (strcmp(fReturn[pushed],"a"))
3681 pic16_emitcode("pop",fReturn[pushed]);
3683 pic16_emitcode("pop","acc");
3689 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3692 /* generate a jump to the return label
3693 * if the next is not the return statement */
3694 if (!(ic->next && ic->next->op == LABEL
3695 && IC_LABEL(ic->next) == returnLabel)) {
3697 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3698 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3702 /*-----------------------------------------------------------------*/
3703 /* genLabel - generates a label */
3704 /*-----------------------------------------------------------------*/
3705 static void genLabel (iCode *ic)
3709 /* special case never generate */
3710 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3711 if (IC_LABEL(ic) == entryLabel)
3714 pic16_emitpLabel(IC_LABEL(ic)->key);
3715 pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3718 /*-----------------------------------------------------------------*/
3719 /* genGoto - generates a goto */
3720 /*-----------------------------------------------------------------*/
3722 static void genGoto (iCode *ic)
3724 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3725 pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3729 /*-----------------------------------------------------------------*/
3730 /* genMultbits :- multiplication of bits */
3731 /*-----------------------------------------------------------------*/
3732 static void genMultbits (operand *left,
3736 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3738 if(!pic16_sameRegs(AOP(result),AOP(right)))
3739 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3741 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3742 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3743 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3748 /*-----------------------------------------------------------------*/
3749 /* genMultOneByte : 8 bit multiplication & division */
3750 /*-----------------------------------------------------------------*/
3751 static void genMultOneByte (operand *left,
3756 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3757 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3758 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3760 /* (if two literals, the value is computed before) */
3761 /* if one literal, literal on the right */
3762 if (AOP_TYPE(left) == AOP_LIT){
3768 /* size is already checked in genMult == 1 */
3769 // size = AOP_SIZE(result);
3771 if (AOP_TYPE(right) == AOP_LIT){
3772 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3773 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3774 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3775 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3777 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3778 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3779 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3780 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3783 pic16_genMult8X8_8 (left, right,result);
3786 /*-----------------------------------------------------------------*/
3787 /* genMultOneWord : 16 bit multiplication */
3788 /*-----------------------------------------------------------------*/
3789 static void genMultOneWord (operand *left,
3794 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3795 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3796 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3798 /* (if two literals, the value is computed before)
3799 * if one literal, literal on the right */
3800 if (AOP_TYPE(left) == AOP_LIT){
3806 /* size is checked already == 2 */
3807 // size = AOP_SIZE(result);
3809 if (AOP_TYPE(right) == AOP_LIT) {
3810 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3811 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3812 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3813 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3815 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3816 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3817 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3818 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3821 pic16_genMult16X16_16(left, right,result);
3824 /*-----------------------------------------------------------------*/
3825 /* genMultOneLong : 32 bit multiplication */
3826 /*-----------------------------------------------------------------*/
3827 static void genMultOneLong (operand *left,
3832 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3833 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3834 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3836 /* (if two literals, the value is computed before)
3837 * if one literal, literal on the right */
3838 if (AOP_TYPE(left) == AOP_LIT){
3844 /* size is checked already == 4 */
3845 // size = AOP_SIZE(result);
3847 if (AOP_TYPE(right) == AOP_LIT) {
3848 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3849 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3850 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3851 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3853 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3854 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3855 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3856 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3859 pic16_genMult32X32_32(left, right,result);
3864 /*-----------------------------------------------------------------*/
3865 /* genMult - generates code for multiplication */
3866 /*-----------------------------------------------------------------*/
3867 static void genMult (iCode *ic)
3869 operand *left = IC_LEFT(ic);
3870 operand *right = IC_RIGHT(ic);
3871 operand *result= IC_RESULT(ic);
3873 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3874 /* assign the amsops */
3875 pic16_aopOp (left,ic,FALSE);
3876 pic16_aopOp (right,ic,FALSE);
3877 pic16_aopOp (result,ic,TRUE);
3879 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3881 /* special cases first *
3883 if (AOP_TYPE(left) == AOP_CRY
3884 && AOP_TYPE(right)== AOP_CRY) {
3885 genMultbits(left,right,result);
3889 /* if both are of size == 1 */
3890 if(AOP_SIZE(left) == 1
3891 && AOP_SIZE(right) == 1) {
3892 genMultOneByte(left,right,result);
3896 /* if both are of size == 2 */
3897 if(AOP_SIZE(left) == 2
3898 && AOP_SIZE(right) == 2) {
3899 genMultOneWord(left, right, result);
3903 /* if both are of size == 4 */
3904 if(AOP_SIZE(left) == 4
3905 && AOP_SIZE(right) == 4) {
3906 genMultOneLong(left, right, result);
3910 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3913 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3914 /* should have been converted to function call */
3918 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3919 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3920 pic16_freeAsmop(result,NULL,ic,TRUE);
3923 /*-----------------------------------------------------------------*/
3924 /* genDivbits :- division of bits */
3925 /*-----------------------------------------------------------------*/
3926 static void genDivbits (operand *left,
3933 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3934 /* the result must be bit */
3935 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3936 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3940 pic16_emitcode("div","ab");
3941 pic16_emitcode("rrc","a");
3942 pic16_aopPut(AOP(result),"c",0);
3945 /*-----------------------------------------------------------------*/
3946 /* genDivOneByte : 8 bit division */
3947 /*-----------------------------------------------------------------*/
3948 static void genDivOneByte (operand *left,
3952 sym_link *opetype = operandType(result);
3957 /* result = divident / divisor
3958 * - divident may be a register or a literal,
3959 * - divisor may be a register or a literal,
3960 * so there are 3 cases (literal / literal is optimized
3961 * by the front-end) to handle.
3962 * In addition we must handle signed and unsigned, which
3963 * result in 6 final different cases -- VR */
3965 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3966 size = AOP_SIZE(result) - 1;
3968 /* signed or unsigned */
3969 if (SPEC_USIGN(opetype)) {
3970 pCodeOp *pct1, /* count */
3973 symbol *label1, *label2, *label3;;
3976 /* unsigned is easy */
3978 pct1 = pic16_popGetTempReg();
3979 pct2 = pic16_popGetTempReg();
3980 pct3 = pic16_popGetTempReg();
3982 label1 = newiTempLabel(NULL);
3983 label2 = newiTempLabel(NULL);
3984 label3 = newiTempLabel(NULL);
3986 /* the following algorithm is extracted from divuint.c */
3988 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
3989 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
3991 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
3993 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
3995 pic16_emitpLabel(label1->key);
3998 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4002 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4006 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4008 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4009 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4011 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4012 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4013 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4015 pic16_emitpLabel( label3->key );
4016 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4017 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4021 pic16_emitpLabel(label2->key);
4022 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4023 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4024 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4026 /* result is in wreg */
4027 if(AOP_TYPE(result) != AOP_ACC)
4028 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4030 pic16_popReleaseTempReg( pct3 );
4031 pic16_popReleaseTempReg( pct2 );
4032 pic16_popReleaseTempReg( pct1 );
4037 /* signed is a little bit more difficult */
4039 /* save the signs of the operands */
4040 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4042 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4043 pic16_emitcode("push","acc"); /* save it on the stack */
4045 /* now sign adjust for both left & right */
4046 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4048 lbl = newiTempLabel(NULL);
4049 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4050 pic16_emitcode("cpl","a");
4051 pic16_emitcode("inc","a");
4052 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4053 pic16_emitcode("mov","b,a");
4055 /* sign adjust left side */
4056 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4059 lbl = newiTempLabel(NULL);
4060 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4061 pic16_emitcode("cpl","a");
4062 pic16_emitcode("inc","a");
4063 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4065 /* now the division */
4066 pic16_emitcode("div","ab");
4067 /* we are interested in the lower order
4069 pic16_emitcode("mov","b,a");
4070 lbl = newiTempLabel(NULL);
4071 pic16_emitcode("pop","acc");
4072 /* if there was an over flow we don't
4073 adjust the sign of the result */
4074 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4075 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4077 pic16_emitcode("clr","a");
4078 pic16_emitcode("subb","a,b");
4079 pic16_emitcode("mov","b,a");
4080 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4082 /* now we are done */
4083 pic16_aopPut(AOP(result),"b",0);
4085 pic16_emitcode("mov","c,b.7");
4086 pic16_emitcode("subb","a,acc");
4089 pic16_aopPut(AOP(result),"a",offset++);
4093 /*-----------------------------------------------------------------*/
4094 /* genDiv - generates code for division */
4095 /*-----------------------------------------------------------------*/
4096 static void genDiv (iCode *ic)
4098 operand *left = IC_LEFT(ic);
4099 operand *right = IC_RIGHT(ic);
4100 operand *result= IC_RESULT(ic);
4103 /* Division is a very lengthy algorithm, so it is better
4104 * to call support routines than inlining algorithm.
4105 * Division functions written here just in case someone
4106 * wants to inline and not use the support libraries -- VR */
4108 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4109 /* assign the amsops */
4110 pic16_aopOp (left,ic,FALSE);
4111 pic16_aopOp (right,ic,FALSE);
4112 pic16_aopOp (result,ic,TRUE);
4114 /* special cases first */
4116 if (AOP_TYPE(left) == AOP_CRY &&
4117 AOP_TYPE(right)== AOP_CRY) {
4118 genDivbits(left,right,result);
4122 /* if both are of size == 1 */
4123 if (AOP_SIZE(left) == 1 &&
4124 AOP_SIZE(right) == 1 ) {
4125 genDivOneByte(left,right,result);
4129 /* should have been converted to function call */
4132 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4133 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4134 pic16_freeAsmop(result,NULL,ic,TRUE);
4137 /*-----------------------------------------------------------------*/
4138 /* genModbits :- modulus of bits */
4139 /*-----------------------------------------------------------------*/
4140 static void genModbits (operand *left,
4147 /* the result must be bit */
4148 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4149 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4153 pic16_emitcode("div","ab");
4154 pic16_emitcode("mov","a,b");
4155 pic16_emitcode("rrc","a");
4156 pic16_aopPut(AOP(result),"c",0);
4159 /*-----------------------------------------------------------------*/
4160 /* genModOneByte : 8 bit modulus */
4161 /*-----------------------------------------------------------------*/
4162 static void genModOneByte (operand *left,
4166 sym_link *opetype = operandType(result);
4170 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4171 /* signed or unsigned */
4172 if (SPEC_USIGN(opetype)) {
4173 /* unsigned is easy */
4174 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4175 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4177 pic16_emitcode("div","ab");
4178 pic16_aopPut(AOP(result),"b",0);
4182 /* signed is a little bit more difficult */
4184 /* save the signs of the operands */
4185 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4188 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4189 pic16_emitcode("push","acc"); /* save it on the stack */
4191 /* now sign adjust for both left & right */
4192 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4195 lbl = newiTempLabel(NULL);
4196 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4197 pic16_emitcode("cpl","a");
4198 pic16_emitcode("inc","a");
4199 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4200 pic16_emitcode("mov","b,a");
4202 /* sign adjust left side */
4203 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4206 lbl = newiTempLabel(NULL);
4207 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4208 pic16_emitcode("cpl","a");
4209 pic16_emitcode("inc","a");
4210 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4212 /* now the multiplication */
4213 pic16_emitcode("div","ab");
4214 /* we are interested in the lower order
4216 lbl = newiTempLabel(NULL);
4217 pic16_emitcode("pop","acc");
4218 /* if there was an over flow we don't
4219 adjust the sign of the result */
4220 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4221 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4223 pic16_emitcode("clr","a");
4224 pic16_emitcode("subb","a,b");
4225 pic16_emitcode("mov","b,a");
4226 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4228 /* now we are done */
4229 pic16_aopPut(AOP(result),"b",0);
4233 /*-----------------------------------------------------------------*/
4234 /* genMod - generates code for division */
4235 /*-----------------------------------------------------------------*/
4236 static void genMod (iCode *ic)
4238 operand *left = IC_LEFT(ic);
4239 operand *right = IC_RIGHT(ic);
4240 operand *result= IC_RESULT(ic);
4242 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4243 /* assign the amsops */
4244 pic16_aopOp (left,ic,FALSE);
4245 pic16_aopOp (right,ic,FALSE);
4246 pic16_aopOp (result,ic,TRUE);
4248 /* special cases first */
4250 if (AOP_TYPE(left) == AOP_CRY &&
4251 AOP_TYPE(right)== AOP_CRY) {
4252 genModbits(left,right,result);
4256 /* if both are of size == 1 */
4257 if (AOP_SIZE(left) == 1 &&
4258 AOP_SIZE(right) == 1 ) {
4259 genModOneByte(left,right,result);
4263 /* should have been converted to function call */
4267 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4268 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4269 pic16_freeAsmop(result,NULL,ic,TRUE);
4272 /*-----------------------------------------------------------------*/
4273 /* genIfxJump :- will create a jump depending on the ifx */
4274 /*-----------------------------------------------------------------*/
4276 note: May need to add parameter to indicate when a variable is in bit space.
4278 static void genIfxJump (iCode *ic, char *jval)
4281 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4282 /* if true label then we jump if condition
4284 if ( IC_TRUE(ic) ) {
4286 if(strcmp(jval,"a") == 0)
4288 else if (strcmp(jval,"c") == 0)
4291 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4292 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4295 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4296 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4300 /* false label is present */
4301 if(strcmp(jval,"a") == 0)
4303 else if (strcmp(jval,"c") == 0)
4306 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4307 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4310 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4311 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4316 /* mark the icode as generated */
4323 /*-----------------------------------------------------------------*/
4325 /*-----------------------------------------------------------------*/
4326 static void genSkip(iCode *ifx,int status_bit)
4328 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4332 if ( IC_TRUE(ifx) ) {
4333 switch(status_bit) {
4348 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4349 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4353 switch(status_bit) {
4367 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4368 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4375 /*-----------------------------------------------------------------*/
4377 /*-----------------------------------------------------------------*/
4378 static void genSkipc(resolvedIfx *rifx)
4380 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4390 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4391 rifx->generated = 1;
4394 /*-----------------------------------------------------------------*/
4396 /*-----------------------------------------------------------------*/
4397 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4399 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4404 if( (rifx->condition ^ invert_condition) & 1)
4409 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4410 rifx->generated = 1;
4414 /*-----------------------------------------------------------------*/
4416 /*-----------------------------------------------------------------*/
4417 static void genSkipz(iCode *ifx, int condition)
4428 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4430 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4433 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4435 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4440 /*-----------------------------------------------------------------*/
4442 /*-----------------------------------------------------------------*/
4443 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4449 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4451 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4454 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4455 rifx->generated = 1;
4459 /*-----------------------------------------------------------------*/
4460 /* genChkZeroes :- greater or less than comparison */
4461 /* For each byte in a literal that is zero, inclusive or the */
4462 /* the corresponding byte in the operand with W */
4463 /* returns true if any of the bytes are zero */
4464 /*-----------------------------------------------------------------*/
4465 static int genChkZeroes(operand *op, int lit, int size)
4472 i = (lit >> (size*8)) & 0xff;
4476 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4478 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4487 /*-----------------------------------------------------------------*/
4488 /* genCmp :- greater or less than comparison */
4489 /*-----------------------------------------------------------------*/
4490 static void genCmp (operand *left,operand *right,
4491 operand *result, iCode *ifx, int sign)
4493 int size; //, offset = 0 ;
4494 unsigned long lit = 0L,i = 0;
4495 resolvedIfx rFalseIfx;
4496 // resolvedIfx rTrueIfx;
4498 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4501 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4502 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4506 resolveIfx(&rFalseIfx,ifx);
4507 truelbl = newiTempLabel(NULL);
4508 size = max(AOP_SIZE(left),AOP_SIZE(right));
4510 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4514 /* if literal is on the right then swap with left */
4515 if ((AOP_TYPE(right) == AOP_LIT)) {
4516 operand *tmp = right ;
4517 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4518 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4521 lit = (lit - 1) & mask;
4524 rFalseIfx.condition ^= 1;
4527 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4528 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4532 //if(IC_TRUE(ifx) == NULL)
4533 /* if left & right are bit variables */
4534 if (AOP_TYPE(left) == AOP_CRY &&
4535 AOP_TYPE(right) == AOP_CRY ) {
4536 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4537 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4539 /* subtract right from left if at the
4540 end the carry flag is set then we know that
4541 left is greater than right */
4543 symbol *lbl = newiTempLabel(NULL);
4546 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4547 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4551 if(AOP_TYPE(right) == AOP_LIT) {
4553 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4555 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4562 genSkipCond(&rFalseIfx,left,size-1,7);
4564 /* no need to compare to 0...*/
4565 /* NOTE: this is a de-generate compare that most certainly
4566 * creates some dead code. */
4567 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4569 if(ifx) ifx->generated = 1;
4576 //i = (lit >> (size*8)) & 0xff;
4577 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4579 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4581 i = ((0-lit) & 0xff);
4584 /* lit is 0x7f, all signed chars are less than
4585 * this except for 0x7f itself */
4586 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4587 genSkipz2(&rFalseIfx,0);
4589 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4590 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4591 genSkipc(&rFalseIfx);
4596 genSkipz2(&rFalseIfx,1);
4598 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4599 genSkipc(&rFalseIfx);
4603 if(ifx) ifx->generated = 1;
4607 /* chars are out of the way. now do ints and longs */
4610 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4617 genSkipCond(&rFalseIfx,left,size,7);
4618 if(ifx) ifx->generated = 1;
4623 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4625 //rFalseIfx.condition ^= 1;
4626 //genSkipCond(&rFalseIfx,left,size,7);
4627 //rFalseIfx.condition ^= 1;
4629 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4630 if(rFalseIfx.condition)
4631 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4633 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4635 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4636 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4637 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4640 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4642 if(rFalseIfx.condition) {
4644 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4650 genSkipc(&rFalseIfx);
4651 pic16_emitpLabel(truelbl->key);
4652 if(ifx) ifx->generated = 1;
4659 if( (lit & 0xff) == 0) {
4660 /* lower byte is zero */
4661 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4662 i = ((lit >> 8) & 0xff) ^0x80;
4663 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4664 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4665 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4666 genSkipc(&rFalseIfx);
4669 if(ifx) ifx->generated = 1;
4674 /* Special cases for signed longs */
4675 if( (lit & 0xffffff) == 0) {
4676 /* lower byte is zero */
4677 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4678 i = ((lit >> 8*3) & 0xff) ^0x80;
4679 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4680 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4681 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4682 genSkipc(&rFalseIfx);
4685 if(ifx) ifx->generated = 1;
4693 if(lit & (0x80 << (size*8))) {
4694 /* lit is negative */
4695 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4697 //genSkipCond(&rFalseIfx,left,size,7);
4699 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4701 if(rFalseIfx.condition)
4702 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4704 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4708 /* lit is positive */
4709 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4710 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4711 if(rFalseIfx.condition)
4712 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4714 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4719 This works, but is only good for ints.
4720 It also requires a "known zero" register.
4721 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4722 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4723 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
4724 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4725 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4726 genSkipc(&rFalseIfx);
4728 pic16_emitpLabel(truelbl->key);
4729 if(ifx) ifx->generated = 1;
4733 /* There are no more special cases, so perform a general compare */
4735 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4736 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4740 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4742 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4744 //rFalseIfx.condition ^= 1;
4745 genSkipc(&rFalseIfx);
4747 pic16_emitpLabel(truelbl->key);
4749 if(ifx) ifx->generated = 1;
4756 /* sign is out of the way. So now do an unsigned compare */
4757 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4760 /* General case - compare to an unsigned literal on the right.*/
4762 i = (lit >> (size*8)) & 0xff;
4763 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4764 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4766 i = (lit >> (size*8)) & 0xff;
4769 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4771 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4773 /* this byte of the lit is zero,
4774 *if it's not the last then OR in the variable */
4776 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4781 pic16_emitpLabel(lbl->key);
4782 // pic16_emitpLabel(truelbl->key);
4783 //if(emitFinalCheck)
4784 genSkipc(&rFalseIfx);
4786 pic16_emitpLabel(truelbl->key);
4788 if(ifx) ifx->generated = 1;
4795 if(AOP_TYPE(left) == AOP_LIT) {
4796 //symbol *lbl = newiTempLabel(NULL);
4798 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4801 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4804 if((lit == 0) && (sign == 0)){
4807 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4809 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4811 genSkipz2(&rFalseIfx,0);
4812 if(ifx) ifx->generated = 1;
4819 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4820 /* degenerate compare can never be true */
4821 if(rFalseIfx.condition == 0)
4822 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4824 if(ifx) ifx->generated = 1;
4829 /* signed comparisons to a literal byte */
4831 int lp1 = (lit+1) & 0xff;
4833 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4836 rFalseIfx.condition ^= 1;
4837 genSkipCond(&rFalseIfx,right,0,7);
4840 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4841 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4842 genSkipz2(&rFalseIfx,1);
4845 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4846 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4847 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4848 rFalseIfx.condition ^= 1;
4849 genSkipc(&rFalseIfx);
4853 /* unsigned comparisons to a literal byte */
4855 switch(lit & 0xff ) {
4857 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4858 genSkipz2(&rFalseIfx,0);
4861 rFalseIfx.condition ^= 1;
4862 genSkipCond(&rFalseIfx,right,0,7);
4866 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4867 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4868 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4869 rFalseIfx.condition ^= 1;
4870 if (AOP_TYPE(result) == AOP_CRY)
4871 genSkipc(&rFalseIfx);
4873 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4874 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4880 if(ifx) ifx->generated = 1;
4881 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
4887 /* Size is greater than 1 */
4895 /* this means lit = 0xffffffff, or -1 */
4898 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4899 rFalseIfx.condition ^= 1;
4900 genSkipCond(&rFalseIfx,right,size,7);
4901 if(ifx) ifx->generated = 1;
4908 if(rFalseIfx.condition) {
4909 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4910 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4913 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4915 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4919 if(rFalseIfx.condition) {
4920 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4921 pic16_emitpLabel(truelbl->key);
4923 rFalseIfx.condition ^= 1;
4924 genSkipCond(&rFalseIfx,right,s,7);
4927 if(ifx) ifx->generated = 1;
4931 if((size == 1) && (0 == (lp1&0xff))) {
4932 /* lower byte of signed word is zero */
4933 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4934 i = ((lp1 >> 8) & 0xff) ^0x80;
4935 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4936 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4937 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4938 rFalseIfx.condition ^= 1;
4939 genSkipc(&rFalseIfx);
4942 if(ifx) ifx->generated = 1;
4946 if(lit & (0x80 << (size*8))) {
4947 /* Lit is less than zero */
4948 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4949 //rFalseIfx.condition ^= 1;
4950 //genSkipCond(&rFalseIfx,left,size,7);
4951 //rFalseIfx.condition ^= 1;
4952 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4953 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4955 if(rFalseIfx.condition)
4956 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4958 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4962 /* Lit is greater than or equal to zero */
4963 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
4964 //rFalseIfx.condition ^= 1;
4965 //genSkipCond(&rFalseIfx,right,size,7);
4966 //rFalseIfx.condition ^= 1;
4968 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4969 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4971 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4972 if(rFalseIfx.condition)
4973 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4975 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4980 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4981 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4985 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4987 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4989 rFalseIfx.condition ^= 1;
4990 //rFalseIfx.condition = 1;
4991 genSkipc(&rFalseIfx);
4993 pic16_emitpLabel(truelbl->key);
4995 if(ifx) ifx->generated = 1;
5000 /* compare word or long to an unsigned literal on the right.*/
5005 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5008 break; /* handled above */
5011 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5013 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5014 genSkipz2(&rFalseIfx,0);
5018 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5020 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5023 if(rFalseIfx.condition)
5024 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5026 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5029 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5030 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5032 rFalseIfx.condition ^= 1;
5033 genSkipc(&rFalseIfx);
5036 pic16_emitpLabel(truelbl->key);
5038 if(ifx) ifx->generated = 1;
5044 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5045 i = (lit >> (size*8)) & 0xff;
5047 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5048 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5051 i = (lit >> (size*8)) & 0xff;
5054 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5056 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5058 /* this byte of the lit is zero,
5059 * if it's not the last then OR in the variable */
5061 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5066 pic16_emitpLabel(lbl->key);
5068 rFalseIfx.condition ^= 1;
5070 genSkipc(&rFalseIfx);
5074 pic16_emitpLabel(truelbl->key);
5075 if(ifx) ifx->generated = 1;
5079 /* Compare two variables */
5081 DEBUGpic16_emitcode(";sign","%d",sign);
5085 /* Sigh. thus sucks... */
5087 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5088 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5089 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5090 pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5091 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5092 pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5094 /* Signed char comparison */
5095 /* Special thanks to Nikolai Golovchenko for this snippet */
5096 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5097 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5098 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5099 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5100 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5101 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5103 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5104 genSkipc(&rFalseIfx);
5106 if(ifx) ifx->generated = 1;
5112 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5113 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5117 /* The rest of the bytes of a multi-byte compare */
5121 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5124 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5125 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5130 pic16_emitpLabel(lbl->key);
5132 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5133 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5134 (AOP_TYPE(result) == AOP_REG)) {
5135 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5136 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5138 genSkipc(&rFalseIfx);
5140 //genSkipc(&rFalseIfx);
5141 if(ifx) ifx->generated = 1;
5148 if ((AOP_TYPE(result) != AOP_CRY)
5149 && AOP_SIZE(result)) {
5150 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5151 // pic16_emitpLabel( rFalseIfx.lbl->key );
5153 pic16_outBitC(result);
5155 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5156 /* if the result is used in the next
5157 ifx conditional branch then generate
5158 code a little differently */
5160 genIfxJump (ifx,"c");
5162 pic16_outBitC(result);
5163 /* leave the result in acc */
5168 /*-----------------------------------------------------------------*/
5169 /* genCmpGt :- greater than comparison */
5170 /*-----------------------------------------------------------------*/
5171 static void genCmpGt (iCode *ic, iCode *ifx)
5173 operand *left, *right, *result;
5174 sym_link *letype , *retype;
5177 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5179 right= IC_RIGHT(ic);
5180 result = IC_RESULT(ic);
5182 letype = getSpec(operandType(left));
5183 retype =getSpec(operandType(right));
5184 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5185 /* assign the amsops */
5186 pic16_aopOp (left,ic,FALSE);
5187 pic16_aopOp (right,ic,FALSE);
5188 pic16_aopOp (result,ic,TRUE);
5190 genCmp(right, left, result, ifx, sign);
5192 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5193 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5194 pic16_freeAsmop(result,NULL,ic,TRUE);
5197 /*-----------------------------------------------------------------*/
5198 /* genCmpLt - less than comparisons */
5199 /*-----------------------------------------------------------------*/
5200 static void genCmpLt (iCode *ic, iCode *ifx)
5202 operand *left, *right, *result;
5203 sym_link *letype , *retype;
5206 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5208 right= IC_RIGHT(ic);
5209 result = IC_RESULT(ic);
5211 letype = getSpec(operandType(left));
5212 retype =getSpec(operandType(right));
5213 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5215 /* assign the amsops */
5216 pic16_aopOp (left,ic,FALSE);
5217 pic16_aopOp (right,ic,FALSE);
5218 pic16_aopOp (result,ic,TRUE);
5220 genCmp(left, right, result, ifx, sign);
5222 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5223 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5224 pic16_freeAsmop(result,NULL,ic,TRUE);
5229 // FIXME reenable literal optimisation when the pic16 port is stable
5231 /*-----------------------------------------------------------------*/
5232 /* genc16bit2lit - compare a 16 bit value to a literal */
5233 /*-----------------------------------------------------------------*/
5234 static void genc16bit2lit(operand *op, int lit, int offset)
5238 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
5239 if( (lit&0xff) == 0)
5244 switch( BYTEofLONG(lit,i)) {
5246 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5249 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5252 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5255 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5256 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5261 switch( BYTEofLONG(lit,i)) {
5263 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5267 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5271 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5274 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5276 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5285 /*-----------------------------------------------------------------*/
5286 /* gencjneshort - compare and jump if not equal */
5287 /*-----------------------------------------------------------------*/
5288 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5290 int size = max(AOP_SIZE(left),AOP_SIZE(right));
5292 int res_offset = 0; /* the result may be a different size then left or right */
5293 int res_size = AOP_SIZE(result);
5295 symbol *lbl, *lbl_done;
5297 unsigned long lit = 0L;
5298 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5300 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5301 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5303 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
5304 resolveIfx(&rIfx,ifx);
5305 lbl = newiTempLabel(NULL);
5306 lbl_done = newiTempLabel(NULL);
5309 /* if the left side is a literal or
5310 if the right is in a pointer register and left
5312 if ((AOP_TYPE(left) == AOP_LIT) ||
5313 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5318 if(AOP_TYPE(right) == AOP_LIT)
5319 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5321 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5322 preserve_result = 1;
5324 if(result && !preserve_result)
5327 for(i = 0; i < AOP_SIZE(result); i++)
5328 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5332 /* if the right side is a literal then anything goes */
5333 if (AOP_TYPE(right) == AOP_LIT &&
5334 AOP_TYPE(left) != AOP_DIR ) {
5337 genc16bit2lit(left, lit, 0);
5339 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5342 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5345 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5346 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5348 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5352 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5354 if(res_offset < res_size-1)
5362 /* if the right side is in a register or in direct space or
5363 if the left is a pointer register & right is not */
5364 else if (AOP_TYPE(right) == AOP_REG ||
5365 AOP_TYPE(right) == AOP_DIR ||
5366 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5367 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5368 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5369 int lbl_key = lbl->key;
5372 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5373 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5375 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5376 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5377 __FUNCTION__,__LINE__);
5381 /* switch(size) { */
5383 /* genc16bit2lit(left, lit, 0); */
5385 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5390 if((AOP_TYPE(left) == AOP_DIR) &&
5391 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5393 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5394 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5396 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5398 switch (lit & 0xff) {
5400 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5403 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5404 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5405 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5409 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5410 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5411 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5412 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5416 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5417 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5422 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5425 if(AOP_TYPE(result) == AOP_CRY) {
5426 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5431 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5433 /* fix me. probably need to check result size too */
5434 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5439 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5440 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5447 if(res_offset < res_size-1)
5452 } else if(AOP_TYPE(right) == AOP_REG &&
5453 AOP_TYPE(left) != AOP_DIR){
5456 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5457 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5458 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5463 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5465 if(res_offset < res_size-1)
5470 /* right is a pointer reg need both a & b */
5472 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5474 pic16_emitcode("mov","b,%s",l);
5475 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5476 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5481 if(result && preserve_result)
5484 for(i = 0; i < AOP_SIZE(result); i++)
5485 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5488 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5490 if(result && preserve_result)
5491 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5494 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5496 pic16_emitpLabel(lbl->key);
5498 if(result && preserve_result)
5501 for(i = 0; i < AOP_SIZE(result); i++)
5502 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5504 pic16_emitpLabel(lbl_done->key);
5507 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5515 /*-----------------------------------------------------------------*/
5516 /* gencjne - compare and jump if not equal */
5517 /*-----------------------------------------------------------------*/
5518 static void gencjne(operand *left, operand *right, iCode *ifx)
5520 symbol *tlbl = newiTempLabel(NULL);
5522 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5523 gencjneshort(left, right, lbl);
5525 pic16_emitcode("mov","a,%s",one);
5526 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5527 pic16_emitcode("","%05d_DS_:",lbl->key+100);
5528 pic16_emitcode("clr","a");
5529 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5531 pic16_emitpLabel(lbl->key);
5532 pic16_emitpLabel(tlbl->key);
5538 /*-----------------------------------------------------------------*/
5539 /* is_LitOp - check if operand has to be treated as literal */
5540 /*-----------------------------------------------------------------*/
5541 static bool is_LitOp(operand *op)
5543 return (AOP_TYPE(op) == AOP_LIT)
5544 || ( (AOP_TYPE(op) == AOP_PCODE)
5545 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5546 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));
5549 /*-----------------------------------------------------------------*/
5550 /* is_LitAOp - check if operand has to be treated as literal */
5551 /*-----------------------------------------------------------------*/
5552 static bool is_LitAOp(asmop *aop)
5554 return (aop->type == AOP_LIT)
5555 || ( (aop->type == AOP_PCODE)
5556 && ( (aop->aopu.pcop->type == PO_LITERAL)
5557 || (aop->aopu.pcop->type == PO_IMMEDIATE) ));
5562 /*-----------------------------------------------------------------*/
5563 /* genCmpEq - generates code for equal to */
5564 /*-----------------------------------------------------------------*/
5565 static void genCmpEq (iCode *ic, iCode *ifx)
5567 operand *left, *right, *result;
5568 symbol *falselbl = newiTempLabel(NULL);
5569 symbol *donelbl = newiTempLabel(NULL);
5571 int preserve_result = 0;
5572 int generate_result = 0;
5575 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5576 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5577 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5579 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5580 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5582 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5584 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5585 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5589 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5591 operand *tmp = right ;
5596 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5597 preserve_result = 1;
5599 if(result && AOP_SIZE(result))
5600 generate_result = 1;
5602 if(generate_result && !preserve_result)
5604 for(i = 0; i < AOP_SIZE(result); i++)
5605 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5608 for(i=0; i < AOP_SIZE(left); i++)
5610 if(AOP_TYPE(left) != AOP_ACC)
5613 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5615 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5618 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
5620 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
5622 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5627 if(generate_result && preserve_result)
5629 for(i = 0; i < AOP_SIZE(result); i++)
5630 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5634 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5636 if(generate_result && preserve_result)
5637 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5639 if(ifx && IC_TRUE(ifx))
5640 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5642 if(ifx && IC_FALSE(ifx))
5643 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5645 pic16_emitpLabel(falselbl->key);
5649 if(ifx && IC_FALSE(ifx))
5650 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
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 pic16_emitpLabel(donelbl->key);
5664 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5665 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5666 pic16_freeAsmop(result,NULL,ic,TRUE);
5672 // old version kept for reference
5674 /*-----------------------------------------------------------------*/
5675 /* genCmpEq - generates code for equal to */
5676 /*-----------------------------------------------------------------*/
5677 static void genCmpEq (iCode *ic, iCode *ifx)
5679 operand *left, *right, *result;
5680 unsigned long lit = 0L;
5682 symbol *falselbl = newiTempLabel(NULL);
5685 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5688 DEBUGpic16_emitcode ("; ifx is non-null","");
5690 DEBUGpic16_emitcode ("; ifx is null","");
5692 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5693 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5694 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5696 size = max(AOP_SIZE(left),AOP_SIZE(right));
5698 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5700 /* if literal, literal on the right or
5701 if the right is in a pointer register and left
5703 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
5704 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5705 operand *tmp = right ;
5711 if(ifx && !AOP_SIZE(result)){
5713 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
5714 /* if they are both bit variables */
5715 if (AOP_TYPE(left) == AOP_CRY &&
5716 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5717 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
5718 if(AOP_TYPE(right) == AOP_LIT){
5719 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5721 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5722 pic16_emitcode("cpl","c");
5723 } else if(lit == 1L) {
5724 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5726 pic16_emitcode("clr","c");
5728 /* AOP_TYPE(right) == AOP_CRY */
5730 symbol *lbl = newiTempLabel(NULL);
5731 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5732 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5733 pic16_emitcode("cpl","c");
5734 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5736 /* if true label then we jump if condition
5738 tlbl = newiTempLabel(NULL);
5739 if ( IC_TRUE(ifx) ) {
5740 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5741 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5743 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5744 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5746 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5749 /* left and right are both bit variables, result is carry */
5752 resolveIfx(&rIfx,ifx);
5754 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5755 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5756 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5757 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5762 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
5764 /* They're not both bit variables. Is the right a literal? */
5765 if(AOP_TYPE(right) == AOP_LIT) {
5766 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5771 switch(lit & 0xff) {
5773 if ( IC_TRUE(ifx) ) {
5774 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5776 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5778 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5779 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5783 if ( IC_TRUE(ifx) ) {
5784 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5786 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5788 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5789 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5793 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5795 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5800 /* end of size == 1 */
5804 genc16bit2lit(left,lit,offset);
5807 /* end of size == 2 */
5812 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5813 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5814 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5815 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5818 /* search for patterns that can be optimized */
5820 genc16bit2lit(left,lit,0);
5824 emitSKPZ; // if hi word unequal
5826 emitSKPNZ; // if hi word equal
5828 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5829 genc16bit2lit(left,lit,2);
5832 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5833 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5837 pic16_emitpLabel(falselbl->key);
5846 } else if(AOP_TYPE(right) == AOP_CRY ) {
5847 /* we know the left is not a bit, but that the right is */
5848 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5849 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5850 pic16_popGet(AOP(right),offset));
5851 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5853 /* if the two are equal, then W will be 0 and the Z bit is set
5854 * we could test Z now, or go ahead and check the high order bytes if
5855 * the variable we're comparing is larger than a byte. */
5858 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5860 if ( IC_TRUE(ifx) ) {
5862 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5863 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5866 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5867 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5871 /* They're both variables that are larger than bits */
5874 tlbl = newiTempLabel(NULL);
5877 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5878 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5880 if ( IC_TRUE(ifx) ) {
5884 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5886 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5887 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
5891 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5894 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5895 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5900 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5902 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5903 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5907 if(s>1 && IC_TRUE(ifx)) {
5908 pic16_emitpLabel(tlbl->key);
5909 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5913 /* mark the icode as generated */
5918 /* if they are both bit variables */
5919 if (AOP_TYPE(left) == AOP_CRY &&
5920 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5921 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
5922 if(AOP_TYPE(right) == AOP_LIT){
5923 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5925 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5926 pic16_emitcode("cpl","c");
5927 } else if(lit == 1L) {
5928 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5930 pic16_emitcode("clr","c");
5932 /* AOP_TYPE(right) == AOP_CRY */
5934 symbol *lbl = newiTempLabel(NULL);
5935 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5936 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5937 pic16_emitcode("cpl","c");
5938 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5941 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5942 pic16_outBitC(result);
5946 genIfxJump (ifx,"c");
5949 /* if the result is used in an arithmetic operation
5950 then put the result in place */
5951 pic16_outBitC(result);
5954 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
5955 gencjne(left,right,result,ifx);
5958 gencjne(left,right,newiTempLabel(NULL));
5960 if(IC_TRUE(ifx)->key)
5961 gencjne(left,right,IC_TRUE(ifx)->key);
5963 gencjne(left,right,IC_FALSE(ifx)->key);
5967 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5968 pic16_aopPut(AOP(result),"a",0);
5973 genIfxJump (ifx,"a");
5977 /* if the result is used in an arithmetic operation
5978 then put the result in place */
5980 if (AOP_TYPE(result) != AOP_CRY)
5981 pic16_outAcc(result);
5983 /* leave the result in acc */
5987 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5988 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5989 pic16_freeAsmop(result,NULL,ic,TRUE);
5993 /*-----------------------------------------------------------------*/
5994 /* ifxForOp - returns the icode containing the ifx for operand */
5995 /*-----------------------------------------------------------------*/
5996 static iCode *ifxForOp ( operand *op, iCode *ic )
5998 /* if true symbol then needs to be assigned */
5999 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6000 if (IS_TRUE_SYMOP(op))
6003 /* if this has register type condition and
6004 the next instruction is ifx with the same operand
6005 and live to of the operand is upto the ifx only then */
6007 && ic->next->op == IFX
6008 && IC_COND(ic->next)->key == op->key
6009 && OP_SYMBOL(op)->liveTo <= ic->next->seq
6011 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6016 ic->next->op == IFX &&
6017 IC_COND(ic->next)->key == op->key) {
6018 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6022 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6024 ic->next->op == IFX)
6025 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6028 ic->next->op == IFX &&
6029 IC_COND(ic->next)->key == op->key) {
6030 DEBUGpic16_emitcode ("; "," key is okay");
6031 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6032 OP_SYMBOL(op)->liveTo,
6037 /* the code below is completely untested
6038 * it just allows ulong2fs.c compile -- VR */
6041 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6042 __FILE__, __FUNCTION__, __LINE__);
6044 /* if this has register type condition and
6045 the next instruction is ifx with the same operand
6046 and live to of the operand is upto the ifx only then */
6048 ic->next->op == IFX &&
6049 IC_COND(ic->next)->key == op->key &&
6050 OP_SYMBOL(op)->liveTo <= ic->next->seq )
6054 ic->next->op == IFX &&
6055 IC_COND(ic->next)->key == op->key) {
6056 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6060 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6061 __FILE__, __FUNCTION__, __LINE__);
6063 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
6068 /*-----------------------------------------------------------------*/
6069 /* genAndOp - for && operation */
6070 /*-----------------------------------------------------------------*/
6071 static void genAndOp (iCode *ic)
6073 operand *left,*right, *result;
6076 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6077 /* note here that && operations that are in an
6078 if statement are taken away by backPatchLabels
6079 only those used in arthmetic operations remain */
6080 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6081 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6082 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6084 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6086 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6087 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6088 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6090 /* if both are bit variables */
6091 /* if (AOP_TYPE(left) == AOP_CRY && */
6092 /* AOP_TYPE(right) == AOP_CRY ) { */
6093 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6094 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6095 /* pic16_outBitC(result); */
6097 /* tlbl = newiTempLabel(NULL); */
6098 /* pic16_toBoolean(left); */
6099 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6100 /* pic16_toBoolean(right); */
6101 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6102 /* pic16_outBitAcc(result); */
6105 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6106 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6107 pic16_freeAsmop(result,NULL,ic,TRUE);
6111 /*-----------------------------------------------------------------*/
6112 /* genOrOp - for || operation */
6113 /*-----------------------------------------------------------------*/
6116 modified this code, but it doesn't appear to ever get called
6119 static void genOrOp (iCode *ic)
6121 operand *left,*right, *result;
6124 /* note here that || operations that are in an
6125 if statement are taken away by backPatchLabels
6126 only those used in arthmetic operations remain */
6127 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6128 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6129 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6130 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6132 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6134 /* if both are bit variables */
6135 if (AOP_TYPE(left) == AOP_CRY &&
6136 AOP_TYPE(right) == AOP_CRY ) {
6137 pic16_emitcode("clrc","");
6138 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6139 AOP(left)->aopu.aop_dir,
6140 AOP(left)->aopu.aop_dir);
6141 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6142 AOP(right)->aopu.aop_dir,
6143 AOP(right)->aopu.aop_dir);
6144 pic16_emitcode("setc","");
6147 tlbl = newiTempLabel(NULL);
6148 pic16_toBoolean(left);
6150 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6151 pic16_toBoolean(right);
6152 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6154 pic16_outBitAcc(result);
6157 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6158 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6159 pic16_freeAsmop(result,NULL,ic,TRUE);
6162 /*-----------------------------------------------------------------*/
6163 /* isLiteralBit - test if lit == 2^n */
6164 /*-----------------------------------------------------------------*/
6165 static int isLiteralBit(unsigned long lit)
6167 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6168 0x100L,0x200L,0x400L,0x800L,
6169 0x1000L,0x2000L,0x4000L,0x8000L,
6170 0x10000L,0x20000L,0x40000L,0x80000L,
6171 0x100000L,0x200000L,0x400000L,0x800000L,
6172 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6173 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6176 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6177 for(idx = 0; idx < 32; idx++)
6183 /*-----------------------------------------------------------------*/
6184 /* continueIfTrue - */
6185 /*-----------------------------------------------------------------*/
6186 static void continueIfTrue (iCode *ic)
6188 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6190 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6194 /*-----------------------------------------------------------------*/
6196 /*-----------------------------------------------------------------*/
6197 static void jumpIfTrue (iCode *ic)
6199 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6201 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6205 /*-----------------------------------------------------------------*/
6206 /* jmpTrueOrFalse - */
6207 /*-----------------------------------------------------------------*/
6208 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6210 // ugly but optimized by peephole
6211 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6213 symbol *nlbl = newiTempLabel(NULL);
6214 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
6215 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6216 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6217 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6220 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6221 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6226 /*-----------------------------------------------------------------*/
6227 /* genAnd - code for and */
6228 /*-----------------------------------------------------------------*/
6229 static void genAnd (iCode *ic, iCode *ifx)
6231 operand *left, *right, *result;
6233 unsigned long lit = 0L;
6238 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6239 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6240 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6241 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6243 resolveIfx(&rIfx,ifx);
6245 /* if left is a literal & right is not then exchange them */
6246 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6247 AOP_NEEDSACC(left)) {
6248 operand *tmp = right ;
6253 /* if result = right then exchange them */
6254 if(pic16_sameRegs(AOP(result),AOP(right))){
6255 operand *tmp = right ;
6260 /* if right is bit then exchange them */
6261 if (AOP_TYPE(right) == AOP_CRY &&
6262 AOP_TYPE(left) != AOP_CRY){
6263 operand *tmp = right ;
6267 if(AOP_TYPE(right) == AOP_LIT)
6268 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6270 size = AOP_SIZE(result);
6272 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6275 // result = bit & yy;
6276 if (AOP_TYPE(left) == AOP_CRY){
6277 // c = bit & literal;
6278 if(AOP_TYPE(right) == AOP_LIT){
6280 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6283 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6286 if(size && (AOP_TYPE(result) == AOP_CRY)){
6287 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6290 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6294 pic16_emitcode("clr","c");
6297 if (AOP_TYPE(right) == AOP_CRY){
6299 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6300 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6303 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6305 pic16_emitcode("rrc","a");
6306 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6312 pic16_outBitC(result);
6314 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6315 genIfxJump(ifx, "c");
6319 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6320 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6321 if((AOP_TYPE(right) == AOP_LIT) &&
6322 (AOP_TYPE(result) == AOP_CRY) &&
6323 (AOP_TYPE(left) != AOP_CRY)){
6324 int posbit = isLiteralBit(lit);
6328 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6331 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6337 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6338 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6340 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6341 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6344 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6345 size = AOP_SIZE(left);
6348 int bp = posbit, ofs=0;
6355 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6356 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
6360 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6361 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6363 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6370 symbol *tlbl = newiTempLabel(NULL);
6371 int sizel = AOP_SIZE(left);
6373 pic16_emitcode("setb","c");
6375 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6376 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6378 if((posbit = isLiteralBit(bytelit)) != 0)
6379 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6381 if(bytelit != 0x0FFL)
6382 pic16_emitcode("anl","a,%s",
6383 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6384 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6389 // bit = left & literal
6391 pic16_emitcode("clr","c");
6392 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6394 // if(left & literal)
6397 jmpTrueOrFalse(ifx, tlbl);
6401 pic16_outBitC(result);
6405 /* if left is same as result */
6406 if(pic16_sameRegs(AOP(result),AOP(left))){
6408 for(;size--; offset++,lit>>=8) {
6409 if(AOP_TYPE(right) == AOP_LIT){
6410 switch(lit & 0xff) {
6412 /* and'ing with 0 has clears the result */
6413 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6414 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6417 /* and'ing with 0xff is a nop when the result and left are the same */
6422 int p = my_powof2( (~lit) & 0xff );
6424 /* only one bit is set in the literal, so use a bcf instruction */
6425 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6426 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6429 pic16_emitcode("movlw","0x%x", (lit & 0xff));
6430 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6431 if(know_W != (lit&0xff))
6432 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6434 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6439 if (AOP_TYPE(left) == AOP_ACC) {
6440 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6442 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6443 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6450 // left & result in different registers
6451 if(AOP_TYPE(result) == AOP_CRY){
6453 // if(size), result in bit
6454 // if(!size && ifx), conditional oper: if(left & right)
6455 symbol *tlbl = newiTempLabel(NULL);
6456 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6458 pic16_emitcode("setb","c");
6460 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6461 pic16_emitcode("anl","a,%s",
6462 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6463 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6468 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6469 pic16_outBitC(result);
6471 jmpTrueOrFalse(ifx, tlbl);
6473 for(;(size--);offset++) {
6475 // result = left & right
6476 if(AOP_TYPE(right) == AOP_LIT){
6477 int t = (lit >> (offset*8)) & 0x0FFL;
6480 pic16_emitcode("clrf","%s",
6481 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6482 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6485 pic16_emitcode("movf","%s,w",
6486 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6487 pic16_emitcode("movwf","%s",
6488 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6489 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6490 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6493 pic16_emitcode("movlw","0x%x",t);
6494 pic16_emitcode("andwf","%s,w",
6495 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6496 pic16_emitcode("movwf","%s",
6497 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6499 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6500 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6501 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6506 if (AOP_TYPE(left) == AOP_ACC) {
6507 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6508 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6510 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6511 pic16_emitcode("andwf","%s,w",
6512 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6513 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6514 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6516 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6517 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6523 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6524 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6525 pic16_freeAsmop(result,NULL,ic,TRUE);
6528 /*-----------------------------------------------------------------*/
6529 /* genOr - code for or */
6530 /*-----------------------------------------------------------------*/
6531 static void genOr (iCode *ic, iCode *ifx)
6533 operand *left, *right, *result;
6535 unsigned long lit = 0L;
6537 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6539 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6540 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6541 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6543 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6545 /* if left is a literal & right is not then exchange them */
6546 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6547 AOP_NEEDSACC(left)) {
6548 operand *tmp = right ;
6553 /* if result = right then exchange them */
6554 if(pic16_sameRegs(AOP(result),AOP(right))){
6555 operand *tmp = right ;
6560 /* if right is bit then exchange them */
6561 if (AOP_TYPE(right) == AOP_CRY &&
6562 AOP_TYPE(left) != AOP_CRY){
6563 operand *tmp = right ;
6568 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6570 if(AOP_TYPE(right) == AOP_LIT)
6571 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6573 size = AOP_SIZE(result);
6577 if (AOP_TYPE(left) == AOP_CRY){
6578 if(AOP_TYPE(right) == AOP_LIT){
6579 // c = bit & literal;
6581 // lit != 0 => result = 1
6582 if(AOP_TYPE(result) == AOP_CRY){
6584 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6585 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6586 // AOP(result)->aopu.aop_dir,
6587 // AOP(result)->aopu.aop_dir);
6589 continueIfTrue(ifx);
6593 // lit == 0 => result = left
6594 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6596 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6599 if (AOP_TYPE(right) == AOP_CRY){
6600 if(pic16_sameRegs(AOP(result),AOP(left))){
6602 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6603 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6604 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6606 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6607 AOP(result)->aopu.aop_dir,
6608 AOP(result)->aopu.aop_dir);
6609 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6610 AOP(right)->aopu.aop_dir,
6611 AOP(right)->aopu.aop_dir);
6612 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6613 AOP(result)->aopu.aop_dir,
6614 AOP(result)->aopu.aop_dir);
6616 if( AOP_TYPE(result) == AOP_ACC) {
6617 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6618 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6619 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6620 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6624 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6625 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6626 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6627 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6629 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6630 AOP(result)->aopu.aop_dir,
6631 AOP(result)->aopu.aop_dir);
6632 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6633 AOP(right)->aopu.aop_dir,
6634 AOP(right)->aopu.aop_dir);
6635 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6636 AOP(left)->aopu.aop_dir,
6637 AOP(left)->aopu.aop_dir);
6638 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6639 AOP(result)->aopu.aop_dir,
6640 AOP(result)->aopu.aop_dir);
6645 symbol *tlbl = newiTempLabel(NULL);
6646 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6649 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6650 if( AOP_TYPE(right) == AOP_ACC) {
6651 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6653 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6654 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6659 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6660 pic16_emitcode(";XXX setb","c");
6661 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6662 AOP(left)->aopu.aop_dir,tlbl->key+100);
6663 pic16_toBoolean(right);
6664 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6665 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6666 jmpTrueOrFalse(ifx, tlbl);
6670 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6677 pic16_outBitC(result);
6679 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6680 genIfxJump(ifx, "c");
6684 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6685 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6686 if((AOP_TYPE(right) == AOP_LIT) &&
6687 (AOP_TYPE(result) == AOP_CRY) &&
6688 (AOP_TYPE(left) != AOP_CRY)){
6690 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6693 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6695 continueIfTrue(ifx);
6698 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6699 // lit = 0, result = boolean(left)
6701 pic16_emitcode(";XXX setb","c");
6702 pic16_toBoolean(right);
6704 symbol *tlbl = newiTempLabel(NULL);
6705 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6707 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6709 genIfxJump (ifx,"a");
6713 pic16_outBitC(result);
6717 /* if left is same as result */
6718 if(pic16_sameRegs(AOP(result),AOP(left))){
6720 for(;size--; offset++,lit>>=8) {
6721 if(AOP_TYPE(right) == AOP_LIT){
6722 if((lit & 0xff) == 0)
6723 /* or'ing with 0 has no effect */
6726 int p = my_powof2(lit & 0xff);
6728 /* only one bit is set in the literal, so use a bsf instruction */
6729 pic16_emitpcode(POC_BSF,
6730 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6732 if(know_W != (lit & 0xff))
6733 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6734 know_W = lit & 0xff;
6735 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6740 if (AOP_TYPE(left) == AOP_ACC) {
6741 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
6742 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6744 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6745 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6747 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6748 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6754 // left & result in different registers
6755 if(AOP_TYPE(result) == AOP_CRY){
6757 // if(size), result in bit
6758 // if(!size && ifx), conditional oper: if(left | right)
6759 symbol *tlbl = newiTempLabel(NULL);
6760 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6761 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6765 pic16_emitcode(";XXX setb","c");
6767 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6768 pic16_emitcode(";XXX orl","a,%s",
6769 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6770 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6775 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6776 pic16_outBitC(result);
6778 jmpTrueOrFalse(ifx, tlbl);
6779 } else for(;(size--);offset++){
6781 // result = left & right
6782 if(AOP_TYPE(right) == AOP_LIT){
6783 int t = (lit >> (offset*8)) & 0x0FFL;
6786 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
6787 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6789 pic16_emitcode("movf","%s,w",
6790 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6791 pic16_emitcode("movwf","%s",
6792 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6795 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6796 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6797 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6799 pic16_emitcode("movlw","0x%x",t);
6800 pic16_emitcode("iorwf","%s,w",
6801 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6802 pic16_emitcode("movwf","%s",
6803 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6809 // faster than result <- left, anl result,right
6810 // and better if result is SFR
6811 if (AOP_TYPE(left) == AOP_ACC) {
6812 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
6813 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6815 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6816 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6818 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6819 pic16_emitcode("iorwf","%s,w",
6820 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6822 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6823 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6828 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6829 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6830 pic16_freeAsmop(result,NULL,ic,TRUE);
6833 /*-----------------------------------------------------------------*/
6834 /* genXor - code for xclusive or */
6835 /*-----------------------------------------------------------------*/
6836 static void genXor (iCode *ic, iCode *ifx)
6838 operand *left, *right, *result;
6840 unsigned long lit = 0L;
6842 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6844 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6845 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6846 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6848 /* if left is a literal & right is not ||
6849 if left needs acc & right does not */
6850 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6851 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6852 operand *tmp = right ;
6857 /* if result = right then exchange them */
6858 if(pic16_sameRegs(AOP(result),AOP(right))){
6859 operand *tmp = right ;
6864 /* if right is bit then exchange them */
6865 if (AOP_TYPE(right) == AOP_CRY &&
6866 AOP_TYPE(left) != AOP_CRY){
6867 operand *tmp = right ;
6871 if(AOP_TYPE(right) == AOP_LIT)
6872 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6874 size = AOP_SIZE(result);
6878 if (AOP_TYPE(left) == AOP_CRY){
6879 if(AOP_TYPE(right) == AOP_LIT){
6880 // c = bit & literal;
6882 // lit>>1 != 0 => result = 1
6883 if(AOP_TYPE(result) == AOP_CRY){
6885 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
6886 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6888 continueIfTrue(ifx);
6891 pic16_emitcode("setb","c");
6895 // lit == 0, result = left
6896 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6898 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6900 // lit == 1, result = not(left)
6901 if(size && pic16_sameRegs(AOP(result),AOP(left))){
6902 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
6903 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
6904 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6907 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6908 pic16_emitcode("cpl","c");
6915 symbol *tlbl = newiTempLabel(NULL);
6916 if (AOP_TYPE(right) == AOP_CRY){
6918 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6921 int sizer = AOP_SIZE(right);
6923 // if val>>1 != 0, result = 1
6924 pic16_emitcode("setb","c");
6926 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6928 // test the msb of the lsb
6929 pic16_emitcode("anl","a,#0xfe");
6930 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6934 pic16_emitcode("rrc","a");
6936 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6937 pic16_emitcode("cpl","c");
6938 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6943 pic16_outBitC(result);
6945 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6946 genIfxJump(ifx, "c");
6950 if(pic16_sameRegs(AOP(result),AOP(left))){
6951 /* if left is same as result */
6952 for(;size--; offset++) {
6953 if(AOP_TYPE(right) == AOP_LIT){
6954 int t = (lit >> (offset*8)) & 0x0FFL;
6958 if (IS_AOP_PREG(left)) {
6959 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6960 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6961 pic16_aopPut(AOP(result),"a",offset);
6963 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6964 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6965 pic16_emitcode("xrl","%s,%s",
6966 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6967 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6970 if (AOP_TYPE(left) == AOP_ACC)
6971 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6973 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6974 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6976 if (IS_AOP_PREG(left)) {
6977 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6978 pic16_aopPut(AOP(result),"a",offset);
6980 pic16_emitcode("xrl","%s,a",
6981 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6987 // left & result in different registers
6988 if(AOP_TYPE(result) == AOP_CRY){
6990 // if(size), result in bit
6991 // if(!size && ifx), conditional oper: if(left ^ right)
6992 symbol *tlbl = newiTempLabel(NULL);
6993 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6995 pic16_emitcode("setb","c");
6997 if((AOP_TYPE(right) == AOP_LIT) &&
6998 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6999 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7001 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7002 pic16_emitcode("xrl","a,%s",
7003 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7005 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7010 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7011 pic16_outBitC(result);
7013 jmpTrueOrFalse(ifx, tlbl);
7014 } else for(;(size--);offset++){
7016 // result = left & right
7017 if(AOP_TYPE(right) == AOP_LIT){
7018 int t = (lit >> (offset*8)) & 0x0FFL;
7021 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7022 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7023 pic16_emitcode("movf","%s,w",
7024 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7025 pic16_emitcode("movwf","%s",
7026 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7029 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7030 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7031 pic16_emitcode("comf","%s,w",
7032 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7033 pic16_emitcode("movwf","%s",
7034 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7037 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7038 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7039 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7040 pic16_emitcode("movlw","0x%x",t);
7041 pic16_emitcode("xorwf","%s,w",
7042 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7043 pic16_emitcode("movwf","%s",
7044 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7050 // faster than result <- left, anl result,right
7051 // and better if result is SFR
7052 if (AOP_TYPE(left) == AOP_ACC) {
7053 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7054 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7056 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7057 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7058 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7059 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7061 if ( AOP_TYPE(result) != AOP_ACC){
7062 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7063 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7069 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7070 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7071 pic16_freeAsmop(result,NULL,ic,TRUE);
7074 /*-----------------------------------------------------------------*/
7075 /* genInline - write the inline code out */
7076 /*-----------------------------------------------------------------*/
7077 static void genInline (iCode *ic)
7079 char *buffer, *bp, *bp1;
7081 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7083 _G.inLine += (!options.asmpeep);
7085 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7086 strcpy(buffer,IC_INLINE(ic));
7088 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7090 /* emit each line as a code */
7096 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7104 /* print label, use this special format with NULL directive
7105 * to denote that the argument should not be indented with tab */
7106 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7113 if ((bp1 != bp) && *bp1)
7114 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7119 _G.inLine -= (!options.asmpeep);
7122 /*-----------------------------------------------------------------*/
7123 /* genRRC - rotate right with carry */
7124 /*-----------------------------------------------------------------*/
7125 static void genRRC (iCode *ic)
7127 operand *left , *result ;
7128 int size, offset = 0, same;
7130 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7132 /* rotate right with carry */
7134 result=IC_RESULT(ic);
7135 pic16_aopOp (left,ic,FALSE);
7136 pic16_aopOp (result,ic,FALSE);
7138 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7140 same = pic16_sameRegs(AOP(result),AOP(left));
7142 size = AOP_SIZE(result);
7144 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7146 /* get the lsb and put it into the carry */
7147 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7154 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7156 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7157 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7163 pic16_freeAsmop(left,NULL,ic,TRUE);
7164 pic16_freeAsmop(result,NULL,ic,TRUE);
7167 /*-----------------------------------------------------------------*/
7168 /* genRLC - generate code for rotate left with carry */
7169 /*-----------------------------------------------------------------*/
7170 static void genRLC (iCode *ic)
7172 operand *left , *result ;
7173 int size, offset = 0;
7176 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7177 /* rotate right with carry */
7179 result=IC_RESULT(ic);
7180 pic16_aopOp (left,ic,FALSE);
7181 pic16_aopOp (result,ic,FALSE);
7183 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7185 same = pic16_sameRegs(AOP(result),AOP(left));
7187 /* move it to the result */
7188 size = AOP_SIZE(result);
7190 /* get the msb and put it into the carry */
7191 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7198 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7200 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7201 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7208 pic16_freeAsmop(left,NULL,ic,TRUE);
7209 pic16_freeAsmop(result,NULL,ic,TRUE);
7213 /* gpasm can get the highest order bit with HIGH/UPPER
7214 * so the following probably is not needed -- VR */
7216 /*-----------------------------------------------------------------*/
7217 /* genGetHbit - generates code get highest order bit */
7218 /*-----------------------------------------------------------------*/
7219 static void genGetHbit (iCode *ic)
7221 operand *left, *result;
7223 result=IC_RESULT(ic);
7224 pic16_aopOp (left,ic,FALSE);
7225 pic16_aopOp (result,ic,FALSE);
7227 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7228 /* get the highest order byte into a */
7229 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7230 if(AOP_TYPE(result) == AOP_CRY){
7231 pic16_emitcode("rlc","a");
7232 pic16_outBitC(result);
7235 pic16_emitcode("rl","a");
7236 pic16_emitcode("anl","a,#0x01");
7237 pic16_outAcc(result);
7241 pic16_freeAsmop(left,NULL,ic,TRUE);
7242 pic16_freeAsmop(result,NULL,ic,TRUE);
7246 /*-----------------------------------------------------------------*/
7247 /* AccRol - rotate left accumulator by known count */
7248 /*-----------------------------------------------------------------*/
7249 static void AccRol (int shCount)
7251 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7252 shCount &= 0x0007; // shCount : 0..7
7257 pic16_emitcode("rl","a");
7260 pic16_emitcode("rl","a");
7261 pic16_emitcode("rl","a");
7264 pic16_emitcode("swap","a");
7265 pic16_emitcode("rr","a");
7268 pic16_emitcode("swap","a");
7271 pic16_emitcode("swap","a");
7272 pic16_emitcode("rl","a");
7275 pic16_emitcode("rr","a");
7276 pic16_emitcode("rr","a");
7279 pic16_emitcode("rr","a");
7285 /*-----------------------------------------------------------------*/
7286 /* AccLsh - left shift accumulator by known count */
7287 /*-----------------------------------------------------------------*/
7288 static void AccLsh (int shCount)
7290 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7296 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7299 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7300 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7303 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7304 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7307 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7310 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7311 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7314 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7315 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7318 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7322 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7325 /*-----------------------------------------------------------------*/
7326 /* AccRsh - right shift accumulator by known count */
7327 /*-----------------------------------------------------------------*/
7328 static void AccRsh (int shCount, int andmask)
7330 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7335 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7336 // andmask = 0; /* no need */
7339 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7340 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7341 // andmask = 0; /* no need */
7344 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7345 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7348 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7351 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7352 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7355 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7356 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7359 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7364 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7366 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7370 /*-----------------------------------------------------------------*/
7371 /* AccSRsh - signed right shift accumulator by known count */
7372 /*-----------------------------------------------------------------*/
7373 static void AccSRsh (int shCount)
7376 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7379 pic16_emitcode("mov","c,acc.7");
7380 pic16_emitcode("rrc","a");
7381 } else if(shCount == 2){
7382 pic16_emitcode("mov","c,acc.7");
7383 pic16_emitcode("rrc","a");
7384 pic16_emitcode("mov","c,acc.7");
7385 pic16_emitcode("rrc","a");
7387 tlbl = newiTempLabel(NULL);
7388 /* rotate right accumulator */
7389 AccRol(8 - shCount);
7390 /* and kill the higher order bits */
7391 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7392 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7393 pic16_emitcode("orl","a,#0x%02x",
7394 (unsigned char)~SRMask[shCount]);
7395 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7400 /*-----------------------------------------------------------------*/
7401 /* shiftR1Left2Result - shift right one byte from left to result */
7402 /*-----------------------------------------------------------------*/
7403 static void shiftR1Left2ResultSigned (operand *left, int offl,
7404 operand *result, int offr,
7409 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7411 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7415 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7417 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7419 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7420 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7426 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7428 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7430 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7431 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7433 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7434 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7440 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7442 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7443 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7446 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7447 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7448 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7450 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7451 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7453 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7457 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7458 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7459 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7460 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
7461 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7465 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7467 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7468 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7470 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7471 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
7472 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7473 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
7474 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7479 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7480 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7481 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7482 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7483 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7484 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7486 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7487 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7488 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7489 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7490 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7496 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7497 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7498 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7499 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7501 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7502 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7503 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7511 /*-----------------------------------------------------------------*/
7512 /* shiftR1Left2Result - shift right one byte from left to result */
7513 /*-----------------------------------------------------------------*/
7514 static void shiftR1Left2Result (operand *left, int offl,
7515 operand *result, int offr,
7516 int shCount, int sign)
7520 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7522 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7524 /* Copy the msb into the carry if signed. */
7526 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7536 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7538 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7539 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7545 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7547 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7548 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7551 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7556 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7558 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7559 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7562 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7563 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7564 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7565 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7569 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7570 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7571 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7575 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7576 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7577 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7579 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7584 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7585 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7586 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7587 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7588 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7593 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7594 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7595 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7604 /*-----------------------------------------------------------------*/
7605 /* shiftL1Left2Result - shift left one byte from left to result */
7606 /*-----------------------------------------------------------------*/
7607 static void shiftL1Left2Result (operand *left, int offl,
7608 operand *result, int offr, int shCount)
7613 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7615 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7616 DEBUGpic16_emitcode ("; ***","same = %d",same);
7617 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7619 /* shift left accumulator */
7620 //AccLsh(shCount); // don't comment out just yet...
7621 // pic16_aopPut(AOP(result),"a",offr);
7625 /* Shift left 1 bit position */
7626 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7628 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7630 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7631 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7635 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7636 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7637 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7638 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7641 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7642 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7643 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7644 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7645 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7648 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7649 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7650 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7653 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7654 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7655 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7656 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7659 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7660 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7661 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7662 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7663 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7666 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7667 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7668 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7672 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7677 /*-----------------------------------------------------------------*/
7678 /* movLeft2Result - move byte from left to result */
7679 /*-----------------------------------------------------------------*/
7680 static void movLeft2Result (operand *left, int offl,
7681 operand *result, int offr)
7684 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7685 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7686 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7688 if (*l == '@' && (IS_AOP_PREG(result))) {
7689 pic16_emitcode("mov","a,%s",l);
7690 pic16_aopPut(AOP(result),"a",offr);
7692 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7693 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7698 /*-----------------------------------------------------------------*/
7699 /* shiftL2Left2Result - shift left two bytes from left to result */
7700 /*-----------------------------------------------------------------*/
7701 static void shiftL2Left2Result (operand *left, int offl,
7702 operand *result, int offr, int shCount)
7704 int same = pic16_sameRegs(AOP(result), AOP(left));
7707 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7709 if (same && (offl != offr)) { // shift bytes
7712 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7713 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7715 } else { // just treat as different later on
7728 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7729 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7730 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7734 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7735 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7741 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7742 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7743 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7744 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7745 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7746 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7747 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7749 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7750 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7754 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7755 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7756 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7757 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7758 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7759 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7760 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7761 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7762 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7763 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7766 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7767 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7768 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7769 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7770 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7780 /* note, use a mov/add for the shift since the mov has a
7781 chance of getting optimized out */
7782 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7783 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7784 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7785 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7786 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7790 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7791 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7797 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7798 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7799 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7800 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7801 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7802 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7803 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7804 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7808 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7809 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7813 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7814 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7815 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7816 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7818 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7819 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7820 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7821 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7822 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7823 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7824 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7825 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7828 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7829 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7830 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7831 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7832 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7837 /*-----------------------------------------------------------------*/
7838 /* shiftR2Left2Result - shift right two bytes from left to result */
7839 /*-----------------------------------------------------------------*/
7840 static void shiftR2Left2Result (operand *left, int offl,
7841 operand *result, int offr,
7842 int shCount, int sign)
7844 int same = pic16_sameRegs(AOP(result), AOP(left));
7846 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7848 if (same && (offl != offr)) { // shift right bytes
7851 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7852 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7854 } else { // just treat as different later on
7866 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7871 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7872 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7874 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7875 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7876 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7877 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7882 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7885 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7886 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7893 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7894 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7895 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7897 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7898 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7899 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7900 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7902 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7903 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7904 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7906 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7907 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7908 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7909 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7910 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7914 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7915 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7919 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7920 pic16_emitpcode(POC_BTFSC,
7921 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
7922 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7930 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7931 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7933 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7934 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7935 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7936 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7938 pic16_emitpcode(POC_BTFSC,
7939 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0, PO_GPR_REGISTER));
7940 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7942 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7943 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7944 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7945 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7947 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7948 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7949 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7950 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7951 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7952 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7953 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7954 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7956 pic16_emitpcode(POC_BTFSC,
7957 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7958 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7960 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7961 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7968 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7969 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7970 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7971 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7974 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7976 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7981 /*-----------------------------------------------------------------*/
7982 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7983 /*-----------------------------------------------------------------*/
7984 static void shiftLLeftOrResult (operand *left, int offl,
7985 operand *result, int offr, int shCount)
7987 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7989 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7990 /* shift left accumulator */
7992 /* or with result */
7993 /* back to result */
7994 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7997 /*-----------------------------------------------------------------*/
7998 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7999 /*-----------------------------------------------------------------*/
8000 static void shiftRLeftOrResult (operand *left, int offl,
8001 operand *result, int offr, int shCount)
8003 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8005 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8006 /* shift right accumulator */
8008 /* or with result */
8009 /* back to result */
8010 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8013 /*-----------------------------------------------------------------*/
8014 /* genlshOne - left shift a one byte quantity by known count */
8015 /*-----------------------------------------------------------------*/
8016 static void genlshOne (operand *result, operand *left, int shCount)
8018 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8019 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8022 /*-----------------------------------------------------------------*/
8023 /* genlshTwo - left shift two bytes by known amount != 0 */
8024 /*-----------------------------------------------------------------*/
8025 static void genlshTwo (operand *result,operand *left, int shCount)
8029 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8030 size = pic16_getDataSize(result);
8032 /* if shCount >= 8 */
8038 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8040 movLeft2Result(left, LSB, result, MSB16);
8042 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8045 /* 1 <= shCount <= 7 */
8048 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8050 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8054 /*-----------------------------------------------------------------*/
8055 /* shiftLLong - shift left one long from left to result */
8056 /* offr = LSB or MSB16 */
8057 /*-----------------------------------------------------------------*/
8058 static void shiftLLong (operand *left, operand *result, int offr )
8060 int size = AOP_SIZE(result);
8061 int same = pic16_sameRegs(AOP(left),AOP(result));
8064 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8066 if (same && (offr == MSB16)) { //shift one byte
8067 for(i=size-1;i>=MSB16;i--) {
8068 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8069 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8072 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8075 if (size >= LSB+offr ){
8077 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8079 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8080 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8084 if(size >= MSB16+offr){
8086 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8088 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8089 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8093 if(size >= MSB24+offr){
8095 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8097 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8098 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8102 if(size > MSB32+offr){
8104 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8106 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8107 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8111 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8115 /*-----------------------------------------------------------------*/
8116 /* genlshFour - shift four byte by a known amount != 0 */
8117 /*-----------------------------------------------------------------*/
8118 static void genlshFour (operand *result, operand *left, int shCount)
8122 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8123 size = AOP_SIZE(result);
8125 /* if shifting more that 3 bytes */
8126 if (shCount >= 24 ) {
8129 /* lowest order of left goes to the highest
8130 order of the destination */
8131 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8133 movLeft2Result(left, LSB, result, MSB32);
8135 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8136 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8137 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8142 /* more than two bytes */
8143 else if ( shCount >= 16 ) {
8144 /* lower order two bytes goes to higher order two bytes */
8146 /* if some more remaining */
8148 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8150 movLeft2Result(left, MSB16, result, MSB32);
8151 movLeft2Result(left, LSB, result, MSB24);
8153 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8154 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8158 /* if more than 1 byte */
8159 else if ( shCount >= 8 ) {
8160 /* lower order three bytes goes to higher order three bytes */
8164 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8166 movLeft2Result(left, LSB, result, MSB16);
8168 else{ /* size = 4 */
8170 movLeft2Result(left, MSB24, result, MSB32);
8171 movLeft2Result(left, MSB16, result, MSB24);
8172 movLeft2Result(left, LSB, result, MSB16);
8173 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8175 else if(shCount == 1)
8176 shiftLLong(left, result, MSB16);
8178 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8179 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8180 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8181 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8186 /* 1 <= shCount <= 7 */
8187 else if(shCount <= 3)
8189 shiftLLong(left, result, LSB);
8190 while(--shCount >= 1)
8191 shiftLLong(result, result, LSB);
8193 /* 3 <= shCount <= 7, optimize */
8195 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8196 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8197 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8201 /*-----------------------------------------------------------------*/
8202 /* genLeftShiftLiteral - left shifting by known count */
8203 /*-----------------------------------------------------------------*/
8204 static void genLeftShiftLiteral (operand *left,
8209 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8212 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8213 pic16_freeAsmop(right,NULL,ic,TRUE);
8215 pic16_aopOp(left,ic,FALSE);
8216 pic16_aopOp(result,ic,FALSE);
8218 size = getSize(operandType(result));
8221 pic16_emitcode("; shift left ","result %d, left %d",size,
8225 /* I suppose that the left size >= result size */
8228 movLeft2Result(left, size, result, size);
8232 else if(shCount >= (size * 8))
8234 pic16_aopPut(AOP(result),zero,size);
8238 genlshOne (result,left,shCount);
8243 genlshTwo (result,left,shCount);
8247 genlshFour (result,left,shCount);
8251 pic16_freeAsmop(left,NULL,ic,TRUE);
8252 pic16_freeAsmop(result,NULL,ic,TRUE);
8255 /*-----------------------------------------------------------------*
8256 * genMultiAsm - repeat assembly instruction for size of register.
8257 * if endian == 1, then the high byte (i.e base address + size of
8258 * register) is used first else the low byte is used first;
8259 *-----------------------------------------------------------------*/
8260 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8265 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8278 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
8283 /*-----------------------------------------------------------------*/
8284 /* genLeftShift - generates code for left shifting */
8285 /*-----------------------------------------------------------------*/
8286 static void genLeftShift (iCode *ic)
8288 operand *left,*right, *result;
8291 symbol *tlbl , *tlbl1;
8294 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8296 right = IC_RIGHT(ic);
8298 result = IC_RESULT(ic);
8300 pic16_aopOp(right,ic,FALSE);
8302 /* if the shift count is known then do it
8303 as efficiently as possible */
8304 if (AOP_TYPE(right) == AOP_LIT) {
8305 genLeftShiftLiteral (left,right,result,ic);
8309 /* shift count is unknown then we have to form
8310 a loop get the loop count in B : Note: we take
8311 only the lower order byte since shifting
8312 more that 32 bits make no sense anyway, ( the
8313 largest size of an object can be only 32 bits ) */
8316 pic16_aopOp(left,ic,FALSE);
8317 pic16_aopOp(result,ic,FALSE);
8319 /* now move the left to the result if they are not the
8321 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8322 AOP_SIZE(result) > 1) {
8324 size = AOP_SIZE(result);
8327 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8328 if (*l == '@' && (IS_AOP_PREG(result))) {
8330 pic16_emitcode("mov","a,%s",l);
8331 pic16_aopPut(AOP(result),"a",offset);
8333 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8334 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8335 //pic16_aopPut(AOP(result),l,offset);
8341 size = AOP_SIZE(result);
8343 /* if it is only one byte then */
8345 if(optimized_for_speed) {
8346 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8347 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8348 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8349 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8350 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8351 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8352 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8353 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
8354 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
8355 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
8356 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8357 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8360 tlbl = newiTempLabel(NULL);
8361 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8362 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8363 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8366 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8367 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8368 pic16_emitpLabel(tlbl->key);
8369 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8370 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8372 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8377 if (pic16_sameRegs(AOP(left),AOP(result))) {
8379 tlbl = newiTempLabel(NULL);
8380 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8381 genMultiAsm(POC_RRCF, result, size,1);
8382 pic16_emitpLabel(tlbl->key);
8383 genMultiAsm(POC_RLCF, result, size,0);
8384 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8386 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8390 //tlbl = newiTempLabel(NULL);
8392 //tlbl1 = newiTempLabel(NULL);
8394 //reAdjustPreg(AOP(result));
8396 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8397 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8398 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8400 //pic16_emitcode("add","a,acc");
8401 //pic16_aopPut(AOP(result),"a",offset++);
8403 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8405 // pic16_emitcode("rlc","a");
8406 // pic16_aopPut(AOP(result),"a",offset++);
8408 //reAdjustPreg(AOP(result));
8410 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8411 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8414 tlbl = newiTempLabel(NULL);
8415 tlbl1= newiTempLabel(NULL);
8417 size = AOP_SIZE(result);
8420 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8422 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8424 /* offset should be 0, 1 or 3 */
8426 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8428 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8430 pic16_emitpcode(POC_MOVWF, pctemp);
8433 pic16_emitpLabel(tlbl->key);
8436 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8438 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
8440 pic16_emitpcode(POC_DECFSZ, pctemp);
8441 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8442 pic16_emitpLabel(tlbl1->key);
8444 pic16_popReleaseTempReg(pctemp);
8448 pic16_freeAsmop (right,NULL,ic,TRUE);
8449 pic16_freeAsmop(left,NULL,ic,TRUE);
8450 pic16_freeAsmop(result,NULL,ic,TRUE);
8453 /*-----------------------------------------------------------------*/
8454 /* genrshOne - right shift a one byte quantity by known count */
8455 /*-----------------------------------------------------------------*/
8456 static void genrshOne (operand *result, operand *left,
8457 int shCount, int sign)
8459 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8460 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8463 /*-----------------------------------------------------------------*/
8464 /* genrshTwo - right shift two bytes by known amount != 0 */
8465 /*-----------------------------------------------------------------*/
8466 static void genrshTwo (operand *result,operand *left,
8467 int shCount, int sign)
8469 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8470 /* if shCount >= 8 */
8474 shiftR1Left2Result(left, MSB16, result, LSB,
8477 movLeft2Result(left, MSB16, result, LSB);
8479 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8482 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8483 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8487 /* 1 <= shCount <= 7 */
8489 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
8492 /*-----------------------------------------------------------------*/
8493 /* shiftRLong - shift right one long from left to result */
8494 /* offl = LSB or MSB16 */
8495 /*-----------------------------------------------------------------*/
8496 static void shiftRLong (operand *left, int offl,
8497 operand *result, int sign)
8499 int size = AOP_SIZE(result);
8500 int same = pic16_sameRegs(AOP(left),AOP(result));
8502 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8504 if (same && (offl == MSB16)) { //shift one byte right
8505 for(i=MSB16;i<size;i++) {
8506 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8507 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8512 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8518 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8520 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8521 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8525 /* add sign of "a" */
8526 pic16_addSign(result, MSB32, sign);
8530 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8532 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8533 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8537 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8539 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8540 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8544 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8547 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8548 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8553 /*-----------------------------------------------------------------*/
8554 /* genrshFour - shift four byte by a known amount != 0 */
8555 /*-----------------------------------------------------------------*/
8556 static void genrshFour (operand *result, operand *left,
8557 int shCount, int sign)
8559 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8560 /* if shifting more that 3 bytes */
8561 if(shCount >= 24 ) {
8564 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8566 movLeft2Result(left, MSB32, result, LSB);
8568 pic16_addSign(result, MSB16, sign);
8570 else if(shCount >= 16){
8573 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8575 movLeft2Result(left, MSB24, result, LSB);
8576 movLeft2Result(left, MSB32, result, MSB16);
8578 pic16_addSign(result, MSB24, sign);
8580 else if(shCount >= 8){
8583 shiftRLong(left, MSB16, result, sign);
8584 else if(shCount == 0){
8585 movLeft2Result(left, MSB16, result, LSB);
8586 movLeft2Result(left, MSB24, result, MSB16);
8587 movLeft2Result(left, MSB32, result, MSB24);
8588 pic16_addSign(result, MSB32, sign);
8590 else{ //shcount >= 2
8591 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8592 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8593 /* the last shift is signed */
8594 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8595 pic16_addSign(result, MSB32, sign);
8598 else{ /* 1 <= shCount <= 7 */
8600 shiftRLong(left, LSB, result, sign);
8602 shiftRLong(result, LSB, result, sign);
8605 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8606 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8607 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8612 /*-----------------------------------------------------------------*/
8613 /* genRightShiftLiteral - right shifting by known count */
8614 /*-----------------------------------------------------------------*/
8615 static void genRightShiftLiteral (operand *left,
8621 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8624 pic16_freeAsmop(right,NULL,ic,TRUE);
8626 pic16_aopOp(left,ic,FALSE);
8627 pic16_aopOp(result,ic,FALSE);
8629 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8632 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8636 lsize = pic16_getDataSize(left);
8637 res_size = pic16_getDataSize(result);
8638 /* test the LEFT size !!! */
8640 /* I suppose that the left size >= result size */
8643 movLeft2Result(left, lsize, result, res_size);
8646 else if(shCount >= (lsize * 8)){
8649 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8651 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8652 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8657 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8658 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8659 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8661 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8666 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8673 genrshOne (result,left,shCount,sign);
8677 genrshTwo (result,left,shCount,sign);
8681 genrshFour (result,left,shCount,sign);
8689 pic16_freeAsmop(left,NULL,ic,TRUE);
8690 pic16_freeAsmop(result,NULL,ic,TRUE);
8693 /*-----------------------------------------------------------------*/
8694 /* genSignedRightShift - right shift of signed number */
8695 /*-----------------------------------------------------------------*/
8696 static void genSignedRightShift (iCode *ic)
8698 operand *right, *left, *result;
8701 symbol *tlbl, *tlbl1 ;
8704 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8706 /* we do it the hard way put the shift count in b
8707 and loop thru preserving the sign */
8708 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8710 right = IC_RIGHT(ic);
8712 result = IC_RESULT(ic);
8714 pic16_aopOp(right,ic,FALSE);
8715 pic16_aopOp(left,ic,FALSE);
8716 pic16_aopOp(result,ic,FALSE);
8719 if ( AOP_TYPE(right) == AOP_LIT) {
8720 genRightShiftLiteral (left,right,result,ic,1);
8723 /* shift count is unknown then we have to form
8724 a loop get the loop count in B : Note: we take
8725 only the lower order byte since shifting
8726 more that 32 bits make no sense anyway, ( the
8727 largest size of an object can be only 32 bits ) */
8729 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8730 //pic16_emitcode("inc","b");
8731 //pic16_freeAsmop (right,NULL,ic,TRUE);
8732 //pic16_aopOp(left,ic,FALSE);
8733 //pic16_aopOp(result,ic,FALSE);
8735 /* now move the left to the result if they are not the
8737 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8738 AOP_SIZE(result) > 1) {
8740 size = AOP_SIZE(result);
8744 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8745 if (*l == '@' && IS_AOP_PREG(result)) {
8747 pic16_emitcode("mov","a,%s",l);
8748 pic16_aopPut(AOP(result),"a",offset);
8750 pic16_aopPut(AOP(result),l,offset);
8752 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8753 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8759 /* mov the highest order bit to OVR */
8760 tlbl = newiTempLabel(NULL);
8761 tlbl1= newiTempLabel(NULL);
8763 size = AOP_SIZE(result);
8766 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8768 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8770 /* offset should be 0, 1 or 3 */
8771 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8773 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8775 pic16_emitpcode(POC_MOVWF, pctemp);
8778 pic16_emitpLabel(tlbl->key);
8780 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
8781 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
8784 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
8787 pic16_emitpcode(POC_DECFSZ, pctemp);
8788 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8789 pic16_emitpLabel(tlbl1->key);
8791 pic16_popReleaseTempReg(pctemp);
8793 size = AOP_SIZE(result);
8795 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8796 pic16_emitcode("rlc","a");
8797 pic16_emitcode("mov","ov,c");
8798 /* if it is only one byte then */
8800 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8802 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8803 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8804 pic16_emitcode("mov","c,ov");
8805 pic16_emitcode("rrc","a");
8806 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8807 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8808 pic16_aopPut(AOP(result),"a",0);
8812 reAdjustPreg(AOP(result));
8813 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8814 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8815 pic16_emitcode("mov","c,ov");
8817 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8819 pic16_emitcode("rrc","a");
8820 pic16_aopPut(AOP(result),"a",offset--);
8822 reAdjustPreg(AOP(result));
8823 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8824 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8829 pic16_freeAsmop(left,NULL,ic,TRUE);
8830 pic16_freeAsmop(result,NULL,ic,TRUE);
8831 pic16_freeAsmop(right,NULL,ic,TRUE);
8834 /*-----------------------------------------------------------------*/
8835 /* genRightShift - generate code for right shifting */
8836 /*-----------------------------------------------------------------*/
8837 static void genRightShift (iCode *ic)
8839 operand *right, *left, *result;
8843 symbol *tlbl, *tlbl1 ;
8845 /* if signed then we do it the hard way preserve the
8846 sign bit moving it inwards */
8847 letype = getSpec(operandType(IC_LEFT(ic)));
8848 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8850 if (!SPEC_USIGN(letype)) {
8851 genSignedRightShift (ic);
8855 /* signed & unsigned types are treated the same : i.e. the
8856 signed is NOT propagated inwards : quoting from the
8857 ANSI - standard : "for E1 >> E2, is equivalent to division
8858 by 2**E2 if unsigned or if it has a non-negative value,
8859 otherwise the result is implementation defined ", MY definition
8860 is that the sign does not get propagated */
8862 right = IC_RIGHT(ic);
8864 result = IC_RESULT(ic);
8866 pic16_aopOp(right,ic,FALSE);
8868 /* if the shift count is known then do it
8869 as efficiently as possible */
8870 if (AOP_TYPE(right) == AOP_LIT) {
8871 genRightShiftLiteral (left,right,result,ic, 0);
8875 /* shift count is unknown then we have to form
8876 a loop get the loop count in B : Note: we take
8877 only the lower order byte since shifting
8878 more that 32 bits make no sense anyway, ( the
8879 largest size of an object can be only 32 bits ) */
8881 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8882 pic16_emitcode("inc","b");
8883 pic16_aopOp(left,ic,FALSE);
8884 pic16_aopOp(result,ic,FALSE);
8886 /* now move the left to the result if they are not the
8888 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8889 AOP_SIZE(result) > 1) {
8891 size = AOP_SIZE(result);
8894 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8895 if (*l == '@' && IS_AOP_PREG(result)) {
8897 pic16_emitcode("mov","a,%s",l);
8898 pic16_aopPut(AOP(result),"a",offset);
8900 pic16_aopPut(AOP(result),l,offset);
8905 tlbl = newiTempLabel(NULL);
8906 tlbl1= newiTempLabel(NULL);
8907 size = AOP_SIZE(result);
8910 /* if it is only one byte then */
8913 tlbl = newiTempLabel(NULL);
8914 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8915 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8916 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8919 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8920 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8921 pic16_emitpLabel(tlbl->key);
8922 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8923 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8925 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8930 reAdjustPreg(AOP(result));
8931 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8932 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8935 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8937 pic16_emitcode("rrc","a");
8938 pic16_aopPut(AOP(result),"a",offset--);
8940 reAdjustPreg(AOP(result));
8942 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8943 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8946 pic16_freeAsmop(left,NULL,ic,TRUE);
8947 pic16_freeAsmop (right,NULL,ic,TRUE);
8948 pic16_freeAsmop(result,NULL,ic,TRUE);
8951 /*-----------------------------------------------------------------*/
8952 /* genUnpackBits - generates code for unpacking bits */
8953 /*-----------------------------------------------------------------*/
8954 static void genUnpackBits (operand *result, char *rname, int ptype)
8961 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8962 etype = getSpec(operandType(result));
8964 /* read the first byte */
8971 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8974 pic16_emitcode("clr","a");
8975 pic16_emitcode("movc","a","@a+dptr");
8980 /* if we have bitdisplacement then it fits */
8981 /* into this byte completely or if length is */
8982 /* less than a byte */
8983 if ((shCnt = SPEC_BSTR(etype)) ||
8984 (SPEC_BLEN(etype) <= 8)) {
8986 /* shift right acc */
8989 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8990 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8992 /* VR -- normally I would use the following, but since we use the hack,
8993 * to avoid the masking from AccRsh, why not mask it right now? */
8996 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8999 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9005 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9006 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9009 /* bit field did not fit in a byte */
9010 rlen = SPEC_BLEN(etype) - 8;
9011 pic16_aopPut(AOP(result),"a",offset++);
9018 pic16_emitcode("inc","%s",rname);
9019 pic16_emitcode("mov","a,@%s",rname);
9023 pic16_emitcode("inc","%s",rname);
9024 pic16_emitcode("movx","a,@%s",rname);
9028 pic16_emitcode("inc","dptr");
9029 pic16_emitcode("movx","a,@dptr");
9033 pic16_emitcode("clr","a");
9034 pic16_emitcode("inc","dptr");
9035 pic16_emitcode("movc","a","@a+dptr");
9039 pic16_emitcode("inc","dptr");
9040 pic16_emitcode("lcall","__gptrget");
9045 /* if we are done */
9049 pic16_aopPut(AOP(result),"a",offset++);
9054 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9055 pic16_aopPut(AOP(result),"a",offset);
9062 static void genDataPointerGet(operand *left,
9066 int size, offset = 0, leoffset=0 ;
9068 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9069 pic16_aopOp(result, ic, FALSE);
9071 size = AOP_SIZE(result);
9072 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9076 /* The following tests may save a redudant movff instruction when
9077 * accessing unions */
9079 /* if they are the same */
9080 if (operandsEqu (left, result)) {
9081 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9087 /* if they are the same registers */
9088 if (pic16_sameRegs(AOP(left),AOP(result))) {
9089 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9095 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9096 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9097 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9104 if ( AOP_TYPE(left) == AOP_PCODE) {
9105 fprintf(stderr,"genDataPointerGet %s, %d\n",
9106 AOP(left)->aopu.pcop->name,
9107 (AOP(left)->aopu.pcop->type == PO_DIR)?
9108 PCOR(AOP(left)->aopu.pcop)->instance:
9109 PCOI(AOP(left)->aopu.pcop)->offset);
9113 if(AOP(left)->aopu.pcop->type == PO_DIR)
9114 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9116 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9119 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9121 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9122 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9123 mov2w(AOP(left), offset); // patch 8
9124 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9126 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9127 pic16_popGet(AOP(left), offset), //patch 8
9128 pic16_popGet(AOP(result), offset)));
9136 pic16_freeAsmop(result,NULL,ic,TRUE);
9139 void pic16_loadFSR0(operand *op)
9141 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9145 /*-----------------------------------------------------------------*/
9146 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
9147 /*-----------------------------------------------------------------*/
9148 static void genNearPointerGet (operand *left,
9153 //regs *preg = NULL ;
9154 sym_link *rtype, *retype;
9155 sym_link *ltype = operandType(left);
9157 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9158 rtype = operandType(result);
9159 retype= getSpec(rtype);
9161 pic16_aopOp(left,ic,FALSE);
9163 // pic16_DumpOp("(left)",left);
9164 // pic16_DumpOp("(result)",result);
9166 /* if left is rematerialisable and
9167 * result is not bit variable type and
9168 * the left is pointer to data space i.e
9169 * lower 128 bytes of space */
9170 if (AOP_TYPE(left) == AOP_PCODE
9171 && !IS_BITFIELD(retype)
9172 && DCL_TYPE(ltype) == POINTER) {
9174 genDataPointerGet (left,result,ic);
9175 pic16_freeAsmop(left, NULL, ic, TRUE);
9179 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9181 /* if the value is already in a pointer register
9182 * then don't need anything more */
9183 if (!AOP_INPREG(AOP(left))) {
9184 /* otherwise get a free pointer register */
9185 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9187 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9188 if( (AOP_TYPE(left) == AOP_PCODE)
9189 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9190 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9192 pic16_loadFSR0( left ); // patch 10
9194 // set up FSR0 with address from left
9195 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9196 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9200 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9202 pic16_aopOp (result,ic,FALSE);
9204 /* if bitfield then unpack the bits */
9205 if (IS_BITFIELD(retype))
9206 genUnpackBits (result, NULL, POINTER);
9208 /* we have can just get the values */
9209 int size = AOP_SIZE(result);
9212 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9215 /* fsr0 is loaded already -- VR */
9216 // pic16_loadFSR0( left );
9218 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9219 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9223 pic16_emitpcode(POC_MOVFF,
9224 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9225 pic16_popGet(AOP(result), offset++)));
9227 pic16_emitpcode(POC_MOVFF,
9228 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9229 pic16_popGet(AOP(result), offset++)));
9233 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9234 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9236 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9240 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9242 pic16_emitcode("mov","a,@%s",rname);
9243 pic16_aopPut(AOP(result),"a",offset);
9245 sprintf(buffer,"@%s",rname);
9246 pic16_aopPut(AOP(result),buffer,offset);
9250 pic16_emitcode("inc","%s",rname);
9255 /* now some housekeeping stuff */
9257 /* we had to allocate for this iCode */
9258 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9259 pic16_freeAsmop(NULL,aop,ic,TRUE);
9261 /* we did not allocate which means left
9262 already in a pointer register, then
9263 if size > 0 && this could be used again
9264 we have to point it back to where it
9266 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9267 if (AOP_SIZE(result) > 1 &&
9268 !OP_SYMBOL(left)->remat &&
9269 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9271 // int size = AOP_SIZE(result) - 1;
9273 // pic16_emitcode("dec","%s",rname);
9278 pic16_freeAsmop(left,NULL,ic,TRUE);
9279 pic16_freeAsmop(result,NULL,ic,TRUE);
9283 /*-----------------------------------------------------------------*/
9284 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
9285 /*-----------------------------------------------------------------*/
9286 static void genPagedPointerGet (operand *left,
9293 sym_link *rtype, *retype;
9295 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9297 rtype = operandType(result);
9298 retype= getSpec(rtype);
9300 pic16_aopOp(left,ic,FALSE);
9302 /* if the value is already in a pointer register
9303 then don't need anything more */
9304 if (!AOP_INPREG(AOP(left))) {
9305 /* otherwise get a free pointer register */
9307 preg = getFreePtr(ic,&aop,FALSE);
9308 pic16_emitcode("mov","%s,%s",
9310 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9311 rname = preg->name ;
9313 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9315 pic16_freeAsmop(left,NULL,ic,TRUE);
9316 pic16_aopOp (result,ic,FALSE);
9318 /* if bitfield then unpack the bits */
9319 if (IS_BITFIELD(retype))
9320 genUnpackBits (result,rname,PPOINTER);
9322 /* we have can just get the values */
9323 int size = AOP_SIZE(result);
9328 pic16_emitcode("movx","a,@%s",rname);
9329 pic16_aopPut(AOP(result),"a",offset);
9334 pic16_emitcode("inc","%s",rname);
9338 /* now some housekeeping stuff */
9340 /* we had to allocate for this iCode */
9341 pic16_freeAsmop(NULL,aop,ic,TRUE);
9343 /* we did not allocate which means left
9344 already in a pointer register, then
9345 if size > 0 && this could be used again
9346 we have to point it back to where it
9348 if (AOP_SIZE(result) > 1 &&
9349 !OP_SYMBOL(left)->remat &&
9350 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9352 int size = AOP_SIZE(result) - 1;
9354 pic16_emitcode("dec","%s",rname);
9359 pic16_freeAsmop(result,NULL,ic,TRUE);
9364 /*-----------------------------------------------------------------*/
9365 /* genFarPointerGet - gget value from far space */
9366 /*-----------------------------------------------------------------*/
9367 static void genFarPointerGet (operand *left,
9368 operand *result, iCode *ic)
9371 sym_link *retype = getSpec(operandType(result));
9373 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9375 pic16_aopOp(left,ic,FALSE);
9377 /* if the operand is already in dptr
9378 then we do nothing else we move the value to dptr */
9379 if (AOP_TYPE(left) != AOP_STR) {
9380 /* if this is remateriazable */
9381 if (AOP_TYPE(left) == AOP_IMMD)
9382 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9383 else { /* we need to get it byte by byte */
9384 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9385 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9386 if (options.model == MODEL_FLAT24)
9388 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9392 /* so dptr know contains the address */
9393 pic16_freeAsmop(left,NULL,ic,TRUE);
9394 pic16_aopOp(result,ic,FALSE);
9396 /* if bit then unpack */
9397 if (IS_BITFIELD(retype))
9398 genUnpackBits(result,"dptr",FPOINTER);
9400 size = AOP_SIZE(result);
9404 pic16_emitcode("movx","a,@dptr");
9405 pic16_aopPut(AOP(result),"a",offset++);
9407 pic16_emitcode("inc","dptr");
9411 pic16_freeAsmop(result,NULL,ic,TRUE);
9414 /*-----------------------------------------------------------------*/
9415 /* genCodePointerGet - get value from code space */
9416 /*-----------------------------------------------------------------*/
9417 static void genCodePointerGet (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",CPOINTER);
9450 size = AOP_SIZE(result);
9454 pic16_emitcode("clr","a");
9455 pic16_emitcode("movc","a,@a+dptr");
9456 pic16_aopPut(AOP(result),"a",offset++);
9458 pic16_emitcode("inc","dptr");
9462 pic16_freeAsmop(result,NULL,ic,TRUE);
9465 /*-----------------------------------------------------------------*/
9466 /* genGenPointerGet - gget value from generic pointer space */
9467 /*-----------------------------------------------------------------*/
9468 static void genGenPointerGet (operand *left,
9469 operand *result, iCode *ic)
9471 int size, offset, lit;
9472 sym_link *retype = getSpec(operandType(result));
9474 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9475 pic16_aopOp(left,ic,FALSE);
9476 pic16_aopOp(result,ic,FALSE);
9477 size = AOP_SIZE(result);
9479 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9481 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9483 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9484 // load FSR0 from immediate
9485 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9487 // pic16_loadFSR0( left );
9492 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9494 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9501 else { /* we need to get it byte by byte */
9502 // set up FSR0 with address from left
9503 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9504 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9510 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9512 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9519 /* if bit then unpack */
9520 if (IS_BITFIELD(retype))
9521 genUnpackBits(result,"BAD",GPOINTER);
9524 pic16_freeAsmop(left,NULL,ic,TRUE);
9525 pic16_freeAsmop(result,NULL,ic,TRUE);
9529 /*-----------------------------------------------------------------*/
9530 /* genConstPointerGet - get value from const generic pointer space */
9531 /*-----------------------------------------------------------------*/
9532 static void genConstPointerGet (operand *left,
9533 operand *result, iCode *ic)
9535 //sym_link *retype = getSpec(operandType(result));
9536 // symbol *albl = newiTempLabel(NULL); // patch 15
9537 // symbol *blbl = newiTempLabel(NULL); //
9538 // PIC_OPCODE poc; // patch 15
9542 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9543 pic16_aopOp(left,ic,FALSE);
9544 pic16_aopOp(result,ic,TRUE);
9545 size = AOP_SIZE(result);
9547 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9549 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9551 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9552 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9553 pic16_emitpLabel(albl->key);
9555 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9557 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9558 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9559 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9560 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9561 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9563 pic16_emitpLabel(blbl->key);
9565 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9569 // set up table pointer
9570 if( (AOP_TYPE(left) == AOP_PCODE)
9571 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9572 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
9574 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9575 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9576 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9577 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9578 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9579 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9583 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9584 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9585 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9591 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9592 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9596 pic16_freeAsmop(left,NULL,ic,TRUE);
9597 pic16_freeAsmop(result,NULL,ic,TRUE);
9602 /*-----------------------------------------------------------------*/
9603 /* genPointerGet - generate code for pointer get */
9604 /*-----------------------------------------------------------------*/
9605 static void genPointerGet (iCode *ic)
9607 operand *left, *result ;
9608 sym_link *type, *etype;
9611 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9614 result = IC_RESULT(ic) ;
9616 /* depending on the type of pointer we need to
9617 move it to the correct pointer register */
9618 type = operandType(left);
9619 etype = getSpec(type);
9622 if (IS_PTR_CONST(type))
9624 if (IS_CODEPTR(type))
9626 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9628 /* if left is of type of pointer then it is simple */
9629 if (IS_PTR(type) && !IS_FUNC(type->next))
9630 p_type = DCL_TYPE(type);
9632 /* we have to go by the storage class */
9633 p_type = PTR_TYPE(SPEC_OCLS(etype));
9635 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9637 if (SPEC_OCLS(etype)->codesp ) {
9638 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9639 //p_type = CPOINTER ;
9642 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9643 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9644 /*p_type = FPOINTER ;*/
9646 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9647 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9648 /* p_type = PPOINTER; */
9650 if (SPEC_OCLS(etype) == idata )
9651 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9652 /* p_type = IPOINTER; */
9654 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9655 /* p_type = POINTER ; */
9658 /* now that we have the pointer type we assign
9659 the pointer values */
9664 genNearPointerGet (left,result,ic);
9668 genPagedPointerGet(left,result,ic);
9672 genFarPointerGet (left,result,ic);
9676 genConstPointerGet (left,result,ic);
9677 //pic16_emitcodePointerGet (left,result,ic);
9682 if (IS_PTR_CONST(type))
9683 genConstPointerGet (left,result,ic);
9686 genGenPointerGet (left,result,ic);
9690 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9691 "genPointerGet: illegal pointer type");
9697 /*-----------------------------------------------------------------*/
9698 /* genPackBits - generates code for packed bit storage */
9699 /*-----------------------------------------------------------------*/
9700 static void genPackBits (sym_link *etype ,
9702 char *rname, int p_type)
9710 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9711 blen = SPEC_BLEN(etype);
9712 bstr = SPEC_BSTR(etype);
9714 if(AOP_TYPE(right) == AOP_LIT) {
9715 if((blen == 1) && (bstr < 8)) {
9717 /* it is a single bit, so use the appropriate bit instructions */
9719 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9721 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9722 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9724 pic16_emitpcode(POC_BSF,
9725 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9727 pic16_emitpcode(POC_BCF,
9728 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9734 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9737 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9739 /* if the bit lenth is less than or */
9740 /* it exactly fits a byte then */
9741 if((shCnt=SPEC_BSTR(etype))
9742 || SPEC_BLEN(etype) <= 8 ) {
9744 /* shift left acc */
9747 /* using PRODL as a temporary register here */
9748 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9754 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9755 // pic16_emitcode ("mov","b,a");
9756 // pic16_emitcode("mov","a,@%s",rname);
9760 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9761 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9762 (unsigned char)(0xff >> (8-bstr))) ));
9763 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9764 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9771 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9772 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9777 if ( SPEC_BLEN(etype) <= 8 )
9780 pic16_emitcode("inc","%s",rname);
9781 rLen = SPEC_BLEN(etype) ;
9785 /* now generate for lengths greater than one byte */
9788 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9798 pic16_emitcode("mov","@%s,a",rname);
9800 pic16_emitcode("mov","@%s,%s",rname,l);
9805 pic16_emitcode("movx","@dptr,a");
9810 DEBUGpic16_emitcode(";lcall","__gptrput");
9813 pic16_emitcode ("inc","%s",rname);
9818 /* last last was not complete */
9820 /* save the byte & read byte */
9823 pic16_emitcode ("mov","b,a");
9824 pic16_emitcode("mov","a,@%s",rname);
9828 pic16_emitcode ("mov","b,a");
9829 pic16_emitcode("movx","a,@dptr");
9833 pic16_emitcode ("push","b");
9834 pic16_emitcode ("push","acc");
9835 pic16_emitcode ("lcall","__gptrget");
9836 pic16_emitcode ("pop","b");
9840 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9841 pic16_emitcode ("orl","a,b");
9844 if (p_type == GPOINTER)
9845 pic16_emitcode("pop","b");
9850 pic16_emitcode("mov","@%s,a",rname);
9854 pic16_emitcode("movx","@dptr,a");
9858 DEBUGpic16_emitcode(";lcall","__gptrput");
9862 /*-----------------------------------------------------------------*/
9863 /* genDataPointerSet - remat pointer to data space */
9864 /*-----------------------------------------------------------------*/
9865 static void genDataPointerSet(operand *right,
9869 int size, offset = 0, resoffset=0 ;
9871 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9872 pic16_aopOp(right,ic,FALSE);
9874 size = AOP_SIZE(right);
9876 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9879 if ( AOP_TYPE(result) == AOP_PCODE) {
9880 fprintf(stderr,"genDataPointerSet %s, %d\n",
9881 AOP(result)->aopu.pcop->name,
9882 (AOP(result)->aopu.pcop->type == PO_DIR)?
9883 PCOR(AOP(result)->aopu.pcop)->instance:
9884 PCOI(AOP(result)->aopu.pcop)->offset);
9888 if(AOP(result)->aopu.pcop->type == PO_DIR)
9889 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9892 if (AOP_TYPE(right) == AOP_LIT) {
9893 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9895 lit = lit >> (8*offset);
9897 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9898 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9900 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9903 mov2w(AOP(right), offset);
9904 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9910 pic16_freeAsmop(right,NULL,ic,TRUE);
9915 /*-----------------------------------------------------------------*/
9916 /* genNearPointerSet - pic16_emitcode for near pointer put */
9917 /*-----------------------------------------------------------------*/
9918 static void genNearPointerSet (operand *right,
9925 sym_link *ptype = operandType(result);
9928 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9929 retype= getSpec(operandType(right));
9930 resetype = getSpec(operandType(result));
9932 pic16_aopOp(result,ic,FALSE);
9934 /* if the result is rematerializable &
9935 * in data space & not a bit variable */
9937 /* and result is not a bit variable */
9938 if (AOP_TYPE(result) == AOP_PCODE
9939 // && AOP_TYPE(result) == AOP_IMMD
9940 && DCL_TYPE(ptype) == POINTER
9941 && !IS_BITFIELD(retype)
9942 && !IS_BITFIELD(resetype)) {
9944 genDataPointerSet (right,result,ic);
9945 pic16_freeAsmop(result,NULL,ic,TRUE);
9949 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9950 pic16_aopOp(right,ic,FALSE);
9951 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9953 /* if the value is already in a pointer register
9954 * then don't need anything more */
9955 if (!AOP_INPREG(AOP(result))) {
9956 /* otherwise get a free pointer register */
9957 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9959 if( (AOP_TYPE(result) == AOP_PCODE)
9960 && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
9961 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
9963 pic16_loadFSR0( result ); // patch 10
9965 // set up FSR0 with address of result
9966 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9967 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9972 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9974 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9976 /* if bitfield then unpack the bits */
9977 if (IS_BITFIELD(resetype)) {
9978 genPackBits (resetype, right, NULL, POINTER);
9980 /* we have can just get the values */
9981 int size = AOP_SIZE(right);
9984 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9986 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9989 //pic16_emitcode("mov","@%s,a",rname);
9990 pic16_emitcode("movf","indf0,w ;1");
9993 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
9994 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
9996 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
9998 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
10000 } else { // no literal //
10002 pic16_emitpcode(POC_MOVFF, //
10003 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10004 pic16_popCopyReg(&pic16_pc_postinc0))); //
10006 pic16_emitpcode(POC_MOVFF, //
10007 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10008 pic16_popCopyReg(&pic16_pc_indf0))); //
10016 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10017 /* now some housekeeping stuff */
10019 /* we had to allocate for this iCode */
10020 pic16_freeAsmop(NULL,aop,ic,TRUE);
10022 /* we did not allocate which means left
10023 * already in a pointer register, then
10024 * if size > 0 && this could be used again
10025 * we have to point it back to where it
10027 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10028 if (AOP_SIZE(right) > 1
10029 && !OP_SYMBOL(result)->remat
10030 && ( OP_SYMBOL(result)->liveTo > ic->seq
10033 int size = AOP_SIZE(right) - 1;
10036 pic16_emitcode("decf","fsr0,f");
10037 //pic16_emitcode("dec","%s",rname);
10041 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10044 pic16_freeAsmop(right,NULL,ic,TRUE);
10045 pic16_freeAsmop(result,NULL,ic,TRUE);
10048 /*-----------------------------------------------------------------*/
10049 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
10050 /*-----------------------------------------------------------------*/
10051 static void genPagedPointerSet (operand *right,
10056 regs *preg = NULL ;
10060 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10062 retype= getSpec(operandType(right));
10064 pic16_aopOp(result,ic,FALSE);
10066 /* if the value is already in a pointer register
10067 then don't need anything more */
10068 if (!AOP_INPREG(AOP(result))) {
10069 /* otherwise get a free pointer register */
10071 preg = getFreePtr(ic,&aop,FALSE);
10072 pic16_emitcode("mov","%s,%s",
10074 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10075 rname = preg->name ;
10077 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10079 pic16_freeAsmop(result,NULL,ic,TRUE);
10080 pic16_aopOp (right,ic,FALSE);
10082 /* if bitfield then unpack the bits */
10083 if (IS_BITFIELD(retype))
10084 genPackBits (retype,right,rname,PPOINTER);
10086 /* we have can just get the values */
10087 int size = AOP_SIZE(right);
10091 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10094 pic16_emitcode("movx","@%s,a",rname);
10097 pic16_emitcode("inc","%s",rname);
10103 /* now some housekeeping stuff */
10105 /* we had to allocate for this iCode */
10106 pic16_freeAsmop(NULL,aop,ic,TRUE);
10108 /* we did not allocate which means left
10109 already in a pointer register, then
10110 if size > 0 && this could be used again
10111 we have to point it back to where it
10113 if (AOP_SIZE(right) > 1 &&
10114 !OP_SYMBOL(result)->remat &&
10115 ( OP_SYMBOL(result)->liveTo > ic->seq ||
10117 int size = AOP_SIZE(right) - 1;
10119 pic16_emitcode("dec","%s",rname);
10124 pic16_freeAsmop(right,NULL,ic,TRUE);
10129 /*-----------------------------------------------------------------*/
10130 /* genFarPointerSet - set value from far space */
10131 /*-----------------------------------------------------------------*/
10132 static void genFarPointerSet (operand *right,
10133 operand *result, iCode *ic)
10136 sym_link *retype = getSpec(operandType(right));
10138 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10139 pic16_aopOp(result,ic,FALSE);
10141 /* if the operand is already in dptr
10142 then we do nothing else we move the value to dptr */
10143 if (AOP_TYPE(result) != AOP_STR) {
10144 /* if this is remateriazable */
10145 if (AOP_TYPE(result) == AOP_IMMD)
10146 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10147 else { /* we need to get it byte by byte */
10148 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10149 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10150 if (options.model == MODEL_FLAT24)
10152 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10156 /* so dptr know contains the address */
10157 pic16_freeAsmop(result,NULL,ic,TRUE);
10158 pic16_aopOp(right,ic,FALSE);
10160 /* if bit then unpack */
10161 if (IS_BITFIELD(retype))
10162 genPackBits(retype,right,"dptr",FPOINTER);
10164 size = AOP_SIZE(right);
10168 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10170 pic16_emitcode("movx","@dptr,a");
10172 pic16_emitcode("inc","dptr");
10176 pic16_freeAsmop(right,NULL,ic,TRUE);
10179 /*-----------------------------------------------------------------*/
10180 /* genGenPointerSet - set value from generic pointer space */
10181 /*-----------------------------------------------------------------*/
10182 static void genGenPointerSet (operand *right,
10183 operand *result, iCode *ic)
10185 int i, size, offset, lit;
10186 sym_link *retype = getSpec(operandType(right));
10188 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10190 pic16_aopOp(result,ic,FALSE);
10191 pic16_aopOp(right,ic,FALSE);
10192 size = AOP_SIZE(right);
10195 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10197 /* if the operand is already in dptr
10198 then we do nothing else we move the value to dptr */
10199 if (AOP_TYPE(result) != AOP_STR) {
10200 /* if this is remateriazable */
10201 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10202 // WARNING: anythig until "else" is untested!
10203 if (AOP_TYPE(result) == AOP_IMMD) {
10204 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10205 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10206 // load FSR0 from immediate
10207 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10211 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10213 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10219 else { /* we need to get it byte by byte */
10220 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10221 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10223 // set up FSR0 with address of result
10224 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10225 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10227 /* hack hack! see if this the FSR. If so don't load W */
10228 if(AOP_TYPE(right) != AOP_ACC) {
10230 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10232 if(AOP_TYPE(right) == AOP_LIT)
10235 // note: pic16_popGet handles sign extension
10236 for(i=0;i<size;i++) {
10237 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10239 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10241 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10246 for(i=0;i<size;i++) {
10248 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10249 pic16_popCopyReg(&pic16_pc_postinc0)));
10251 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10252 pic16_popCopyReg(&pic16_pc_indf0)));
10258 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10259 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10261 } // if (AOP_TYPE(result) != AOP_IMMD)
10263 } // if (AOP_TYPE(result) != AOP_STR)
10264 /* so dptr know contains the address */
10267 /* if bit then unpack */
10268 if (IS_BITFIELD(retype))
10269 genPackBits(retype,right,"dptr",GPOINTER);
10271 size = AOP_SIZE(right);
10274 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
10276 // set up FSR0 with address of result
10277 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10278 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10281 if (AOP_TYPE(right) == AOP_LIT) {
10282 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10284 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10286 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10288 } else { // no literal
10290 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10292 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10300 pic16_freeAsmop(right,NULL,ic,TRUE);
10301 pic16_freeAsmop(result,NULL,ic,TRUE);
10304 /*-----------------------------------------------------------------*/
10305 /* genPointerSet - stores the value into a pointer location */
10306 /*-----------------------------------------------------------------*/
10307 static void genPointerSet (iCode *ic)
10309 operand *right, *result ;
10310 sym_link *type, *etype;
10313 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10315 right = IC_RIGHT(ic);
10316 result = IC_RESULT(ic) ;
10318 /* depending on the type of pointer we need to
10319 move it to the correct pointer register */
10320 type = operandType(result);
10321 etype = getSpec(type);
10322 /* if left is of type of pointer then it is simple */
10323 if (IS_PTR(type) && !IS_FUNC(type->next)) {
10324 p_type = DCL_TYPE(type);
10327 /* we have to go by the storage class */
10328 p_type = PTR_TYPE(SPEC_OCLS(etype));
10330 /* if (SPEC_OCLS(etype)->codesp ) { */
10331 /* p_type = CPOINTER ; */
10334 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10335 /* p_type = FPOINTER ; */
10337 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10338 /* p_type = PPOINTER ; */
10340 /* if (SPEC_OCLS(etype) == idata ) */
10341 /* p_type = IPOINTER ; */
10343 /* p_type = POINTER ; */
10346 /* now that we have the pointer type we assign
10347 the pointer values */
10352 genNearPointerSet (right,result,ic);
10356 genPagedPointerSet (right,result,ic);
10360 genFarPointerSet (right,result,ic);
10364 genGenPointerSet (right,result,ic);
10368 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10369 "genPointerSet: illegal pointer type");
10373 /*-----------------------------------------------------------------*/
10374 /* genIfx - generate code for Ifx statement */
10375 /*-----------------------------------------------------------------*/
10376 static void genIfx (iCode *ic, iCode *popIc)
10378 operand *cond = IC_COND(ic);
10381 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10383 pic16_aopOp(cond,ic,FALSE);
10385 /* get the value into acc */
10386 if (AOP_TYPE(cond) != AOP_CRY)
10387 pic16_toBoolean(cond);
10390 /* the result is now in the accumulator */
10391 pic16_freeAsmop(cond,NULL,ic,TRUE);
10393 /* if there was something to be popped then do it */
10397 /* if the condition is a bit variable */
10398 if (isbit && IS_ITEMP(cond) &&
10400 genIfxJump(ic,SPIL_LOC(cond)->rname);
10401 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10404 if (isbit && !IS_ITEMP(cond))
10405 genIfxJump(ic,OP_SYMBOL(cond)->rname);
10407 genIfxJump(ic,"a");
10413 /*-----------------------------------------------------------------*/
10414 /* genAddrOf - generates code for address of */
10415 /*-----------------------------------------------------------------*/
10416 static void genAddrOf (iCode *ic)
10418 operand *result, *left;
10420 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
10421 pCodeOp *pcop0, *pcop1, *pcop2;
10423 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10425 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10426 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10428 sym = OP_SYMBOL( left );
10430 size = AOP_SIZE(IC_RESULT(ic));
10432 // if(pic16_debug_verbose) {
10433 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10434 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10437 /* Assume that what we want the address of is in data space
10438 * since there is no stack on the PIC, yet! -- VR */
10440 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10443 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10446 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10450 pic16_emitpcode(POC_MOVLW, pcop0);
10451 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10452 pic16_emitpcode(POC_MOVLW, pcop1);
10453 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10454 pic16_emitpcode(POC_MOVLW, pcop2);
10455 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10458 pic16_emitpcode(POC_MOVLW, pcop0);
10459 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10460 pic16_emitpcode(POC_MOVLW, pcop1);
10461 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10463 pic16_emitpcode(POC_MOVLW, pcop0);
10464 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10467 pic16_freeAsmop(result,NULL,ic,TRUE);
10468 pic16_freeAsmop(left, NULL, ic, FALSE);
10473 /*-----------------------------------------------------------------*/
10474 /* genFarFarAssign - assignment when both are in far space */
10475 /*-----------------------------------------------------------------*/
10476 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10478 int size = AOP_SIZE(right);
10481 /* first push the right side on to the stack */
10483 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10485 pic16_emitcode ("push","acc");
10488 pic16_freeAsmop(right,NULL,ic,FALSE);
10489 /* now assign DPTR to result */
10490 pic16_aopOp(result,ic,FALSE);
10491 size = AOP_SIZE(result);
10493 pic16_emitcode ("pop","acc");
10494 pic16_aopPut(AOP(result),"a",--offset);
10496 pic16_freeAsmop(result,NULL,ic,FALSE);
10501 /*-----------------------------------------------------------------*/
10502 /* genAssign - generate code for assignment */
10503 /*-----------------------------------------------------------------*/
10504 static void genAssign (iCode *ic)
10506 operand *result, *right;
10507 int size, offset,know_W;
10508 unsigned long lit = 0L;
10510 result = IC_RESULT(ic);
10511 right = IC_RIGHT(ic) ;
10513 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10515 /* if they are the same */
10516 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10519 pic16_aopOp(right,ic,FALSE);
10520 pic16_aopOp(result,ic,TRUE);
10522 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10524 /* if they are the same registers */
10525 if (pic16_sameRegs(AOP(right),AOP(result)))
10528 /* if the result is a bit */
10529 if (AOP_TYPE(result) == AOP_CRY) {
10530 /* if the right size is a literal then
10531 we know what the value is */
10532 if (AOP_TYPE(right) == AOP_LIT) {
10534 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10535 pic16_popGet(AOP(result),0));
10537 if (((int) operandLitValue(right)))
10538 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10539 AOP(result)->aopu.aop_dir,
10540 AOP(result)->aopu.aop_dir);
10542 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10543 AOP(result)->aopu.aop_dir,
10544 AOP(result)->aopu.aop_dir);
10548 /* the right is also a bit variable */
10549 if (AOP_TYPE(right) == AOP_CRY) {
10550 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10551 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10552 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10554 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10555 AOP(result)->aopu.aop_dir,
10556 AOP(result)->aopu.aop_dir);
10557 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10558 AOP(right)->aopu.aop_dir,
10559 AOP(right)->aopu.aop_dir);
10560 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10561 AOP(result)->aopu.aop_dir,
10562 AOP(result)->aopu.aop_dir);
10566 /* we need to or */
10567 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10568 pic16_toBoolean(right);
10570 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10571 //pic16_aopPut(AOP(result),"a",0);
10575 /* bit variables done */
10577 size = AOP_SIZE(result);
10580 if(AOP_TYPE(right) == AOP_LIT) {
10581 if(!IS_FLOAT(operandType( right )))
10582 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10585 unsigned long lit_int;
10589 /* take care if literal is a float */
10590 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10591 lit = info.lit_int;
10595 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10596 // sizeof(unsigned long int), sizeof(float));
10598 if(AOP_TYPE(right) != AOP_LIT
10599 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10600 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10602 // set up table pointer
10603 if( (AOP_TYPE(right) == AOP_PCODE)
10604 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10605 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10607 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10608 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10609 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10610 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10611 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10612 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10614 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10615 pic16_popCopyReg(&pic16_pc_tblptrl)));
10616 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10617 pic16_popCopyReg(&pic16_pc_tblptrh)));
10618 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10619 pic16_popCopyReg(&pic16_pc_tblptru)));
10622 size = min(AOP_SIZE(right), AOP_SIZE(result));
10624 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10625 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10626 pic16_popGet(AOP(result),offset)));
10630 if(AOP_SIZE(result) > AOP_SIZE(right)) {
10631 size = AOP_SIZE(result) - AOP_SIZE(right);
10633 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10642 /* VR - What is this?! */
10643 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10644 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10645 if(aopIdx(AOP(result),0) == 4) {
10646 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10648 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10649 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10653 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10658 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10659 if(AOP_TYPE(right) == AOP_LIT) {
10661 if(know_W != (lit&0xff))
10662 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10664 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10666 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10670 } else if (AOP_TYPE(right) == AOP_CRY) {
10671 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10673 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10674 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10676 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10677 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10678 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10680 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10683 /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10684 normally should work, but mind that the W register live range
10685 is not checked, so if the code generator assumes that the W
10686 is already loaded after such a pair, wrong code will be generated.
10688 Checking the live range is the next step.
10689 This is experimental code yet and has not been fully tested yet.
10690 USE WITH CARE. Revert to old code by setting 0 to the condition above.
10691 Vangelis Rokas 030603 (vrokas@otenet.gr) */
10693 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10695 /* This is the old code, which is assumed(?!) that works fine(!?) */
10697 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10698 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10707 pic16_freeAsmop (right,NULL,ic,FALSE);
10708 pic16_freeAsmop (result,NULL,ic,TRUE);
10711 /*-----------------------------------------------------------------*/
10712 /* genJumpTab - generates code for jump table */
10713 /*-----------------------------------------------------------------*/
10714 static void genJumpTab (iCode *ic)
10719 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10721 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10722 /* get the condition into accumulator */
10723 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10725 /* multiply by three */
10726 pic16_emitcode("add","a,acc");
10727 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10729 jtab = newiTempLabel(NULL);
10730 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10731 pic16_emitcode("jmp","@a+dptr");
10732 pic16_emitcode("","%05d_DS_:",jtab->key+100);
10734 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10735 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10737 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10738 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10739 pic16_emitpLabel(jtab->key);
10741 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10743 /* now generate the jump labels */
10744 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10745 jtab = setNextItem(IC_JTLABELS(ic))) {
10746 pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10747 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10753 /*-----------------------------------------------------------------*/
10754 /* genMixedOperation - gen code for operators between mixed types */
10755 /*-----------------------------------------------------------------*/
10757 TSD - Written for the PIC port - but this unfortunately is buggy.
10758 This routine is good in that it is able to efficiently promote
10759 types to different (larger) sizes. Unfortunately, the temporary
10760 variables that are optimized out by this routine are sometimes
10761 used in other places. So until I know how to really parse the
10762 iCode tree, I'm going to not be using this routine :(.
10764 static int genMixedOperation (iCode *ic)
10767 operand *result = IC_RESULT(ic);
10768 sym_link *ctype = operandType(IC_LEFT(ic));
10769 operand *right = IC_RIGHT(ic);
10775 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10777 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10783 nextright = IC_RIGHT(nextic);
10784 nextleft = IC_LEFT(nextic);
10785 nextresult = IC_RESULT(nextic);
10787 pic16_aopOp(right,ic,FALSE);
10788 pic16_aopOp(result,ic,FALSE);
10789 pic16_aopOp(nextright, nextic, FALSE);
10790 pic16_aopOp(nextleft, nextic, FALSE);
10791 pic16_aopOp(nextresult, nextic, FALSE);
10793 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10795 operand *t = right;
10799 pic16_emitcode(";remove right +","");
10801 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10803 operand *t = right;
10807 pic16_emitcode(";remove left +","");
10811 big = AOP_SIZE(nextleft);
10812 small = AOP_SIZE(nextright);
10814 switch(nextic->op) {
10817 pic16_emitcode(";optimize a +","");
10818 /* if unsigned or not an integral type */
10819 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10820 pic16_emitcode(";add a bit to something","");
10823 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10825 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10826 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10827 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10829 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10837 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10838 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10839 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10842 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10844 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10845 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10846 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10847 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10848 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10851 pic16_emitcode("rlf","known_zero,w");
10858 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10859 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10860 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10862 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10872 pic16_freeAsmop(right,NULL,ic,TRUE);
10873 pic16_freeAsmop(result,NULL,ic,TRUE);
10874 pic16_freeAsmop(nextright,NULL,ic,TRUE);
10875 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10877 nextic->generated = 1;
10884 /*-----------------------------------------------------------------*/
10885 /* genCast - gen code for casting */
10886 /*-----------------------------------------------------------------*/
10887 static void genCast (iCode *ic)
10889 operand *result = IC_RESULT(ic);
10890 sym_link *ctype = operandType(IC_LEFT(ic));
10891 sym_link *rtype = operandType(IC_RIGHT(ic));
10892 operand *right = IC_RIGHT(ic);
10895 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10896 /* if they are equivalent then do nothing */
10897 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10900 pic16_aopOp(right,ic,FALSE) ;
10901 pic16_aopOp(result,ic,FALSE);
10903 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10905 /* if the result is a bit */
10906 if (AOP_TYPE(result) == AOP_CRY) {
10908 /* if the right size is a literal then
10909 * we know what the value is */
10910 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10912 if (AOP_TYPE(right) == AOP_LIT) {
10913 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10914 pic16_popGet(AOP(result),0));
10916 if (((int) operandLitValue(right)))
10917 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10918 AOP(result)->aopu.aop_dir,
10919 AOP(result)->aopu.aop_dir);
10921 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10922 AOP(result)->aopu.aop_dir,
10923 AOP(result)->aopu.aop_dir);
10927 /* the right is also a bit variable */
10928 if (AOP_TYPE(right) == AOP_CRY) {
10930 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10932 pic16_emitcode("clrc","");
10933 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10934 AOP(right)->aopu.aop_dir,
10935 AOP(right)->aopu.aop_dir);
10936 pic16_aopPut(AOP(result),"c",0);
10940 /* we need to or */
10941 if (AOP_TYPE(right) == AOP_REG) {
10942 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10943 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10944 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10946 pic16_toBoolean(right);
10947 pic16_aopPut(AOP(result),"a",0);
10951 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10954 size = AOP_SIZE(result);
10956 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10958 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
10959 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10960 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10963 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
10968 /* if they are the same size : or less */
10969 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10971 /* if they are in the same place */
10972 if (pic16_sameRegs(AOP(right),AOP(result)))
10975 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10977 if (IS_PTR_CONST(rtype))
10979 if (IS_CODEPTR(rtype))
10981 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10984 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10986 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10988 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10991 if(AOP_TYPE(right) == AOP_IMMD) {
10992 pCodeOp *pcop0, *pcop1, *pcop2;
10993 symbol *sym = OP_SYMBOL( right );
10995 size = AOP_SIZE(result);
10997 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10999 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11001 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11004 pic16_emitpcode(POC_MOVLW, pcop0);
11005 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11006 pic16_emitpcode(POC_MOVLW, pcop1);
11007 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11008 pic16_emitpcode(POC_MOVLW, pcop2);
11009 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11012 pic16_emitpcode(POC_MOVLW, pcop0);
11013 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11014 pic16_emitpcode(POC_MOVLW, pcop1);
11015 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11017 pic16_emitpcode(POC_MOVLW, pcop0);
11018 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11022 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11023 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11024 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11025 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11026 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11027 if(AOP_SIZE(result) <2)
11028 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11030 /* if they in different places then copy */
11031 size = AOP_SIZE(result);
11034 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11035 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11042 /* if the result is of type pointer */
11043 if (IS_PTR(ctype)) {
11045 sym_link *type = operandType(right);
11046 sym_link *etype = getSpec(type);
11048 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
11050 /* pointer to generic pointer */
11051 if (IS_GENPTR(ctype)) {
11055 p_type = DCL_TYPE(type);
11057 /* we have to go by the storage class */
11058 p_type = PTR_TYPE(SPEC_OCLS(etype));
11060 /* if (SPEC_OCLS(etype)->codesp ) */
11061 /* p_type = CPOINTER ; */
11063 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11064 /* p_type = FPOINTER ; */
11066 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11067 /* p_type = PPOINTER; */
11069 /* if (SPEC_OCLS(etype) == idata ) */
11070 /* p_type = IPOINTER ; */
11072 /* p_type = POINTER ; */
11075 /* the first two bytes are known */
11076 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
11077 size = GPTRSIZE - 1;
11080 if(offset < AOP_SIZE(right)) {
11081 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
11082 if ((AOP_TYPE(right) == AOP_PCODE) &&
11083 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11084 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11085 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11087 pic16_aopPut(AOP(result),
11088 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11092 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11095 /* the last byte depending on type */
11099 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11102 pic16_emitcode(";BUG!? ","%d",__LINE__);
11106 pic16_emitcode(";BUG!? ","%d",__LINE__);
11110 pic16_emitcode(";BUG!? ","%d",__LINE__);
11115 /* this should never happen */
11116 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11117 "got unknown pointer type");
11120 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
11124 /* just copy the pointers */
11125 size = AOP_SIZE(result);
11128 pic16_aopPut(AOP(result),
11129 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11138 /* so we now know that the size of destination is greater
11139 than the size of the source.
11140 Now, if the next iCode is an operator then we might be
11141 able to optimize the operation without performing a cast.
11143 if(genMixedOperation(ic))
11146 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11148 /* we move to result for the size of source */
11149 size = AOP_SIZE(right);
11152 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11153 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11157 /* now depending on the sign of the destination */
11158 size = AOP_SIZE(result) - AOP_SIZE(right);
11159 /* if unsigned or not an integral type */
11160 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11162 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11164 /* we need to extend the sign :( */
11167 /* Save one instruction of casting char to int */
11168 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11169 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11170 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
11172 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11175 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11177 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11179 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
11182 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
11187 pic16_freeAsmop(right,NULL,ic,TRUE);
11188 pic16_freeAsmop(result,NULL,ic,TRUE);
11192 /*-----------------------------------------------------------------*/
11193 /* genDjnz - generate decrement & jump if not zero instrucion */
11194 /*-----------------------------------------------------------------*/
11195 static int genDjnz (iCode *ic, iCode *ifx)
11197 symbol *lbl, *lbl1;
11198 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11203 /* if the if condition has a false label
11204 then we cannot save */
11208 /* if the minus is not of the form
11210 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11211 !IS_OP_LITERAL(IC_RIGHT(ic)))
11214 if (operandLitValue(IC_RIGHT(ic)) != 1)
11217 /* if the size of this greater than one then no
11219 if (getSize(operandType(IC_RESULT(ic))) > 1)
11222 /* otherwise we can save BIG */
11223 lbl = newiTempLabel(NULL);
11224 lbl1= newiTempLabel(NULL);
11226 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11228 if (IS_AOP_PREG(IC_RESULT(ic))) {
11229 pic16_emitcode("dec","%s",
11230 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11231 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11232 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11236 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11237 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11239 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11240 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
11243 /* pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11244 /* pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11245 /* pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11246 /* pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11249 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11250 ifx->generated = 1;
11254 /*-----------------------------------------------------------------*/
11255 /* genReceive - generate code for a receive iCode */
11256 /*-----------------------------------------------------------------*/
11257 static void genReceive (iCode *ic)
11259 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11262 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11263 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
11265 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11267 if (isOperandInFarSpace(IC_RESULT(ic)) &&
11268 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11269 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11271 int size = getSize(operandType(IC_RESULT(ic)));
11272 int offset = pic16_fReturnSizePic - size;
11276 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11277 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11281 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
11283 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11284 size = AOP_SIZE(IC_RESULT(ic));
11287 pic16_emitcode ("pop","acc");
11288 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11291 DEBUGpic16_emitcode ("; ***","2 %s %d",__FUNCTION__,__LINE__);
11294 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11296 assignResultValue(IC_RESULT(ic), 0);
11299 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11302 /*-----------------------------------------------------------------*/
11303 /* genDummyRead - generate code for dummy read of volatiles */
11304 /*-----------------------------------------------------------------*/
11306 genDummyRead (iCode * ic)
11308 pic16_emitcode ("; genDummyRead","");
11309 pic16_emitcode ("; not implemented","");
11314 /*-----------------------------------------------------------------*/
11315 /* genpic16Code - generate code for pic16 based controllers */
11316 /*-----------------------------------------------------------------*/
11318 * At this point, ralloc.c has gone through the iCode and attempted
11319 * to optimize in a way suitable for a PIC. Now we've got to generate
11320 * PIC instructions that correspond to the iCode.
11322 * Once the instructions are generated, we'll pass through both the
11323 * peep hole optimizer and the pCode optimizer.
11324 *-----------------------------------------------------------------*/
11326 void genpic16Code (iCode *lic)
11331 lineHead = lineCurr = NULL;
11333 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11334 pic16_addpBlock(pb);
11337 /* if debug information required */
11338 if (options.debug && currFunc) {
11340 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11345 for (ic = lic ; ic ; ic = ic->next ) {
11347 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11348 if ( cln != ic->lineno ) {
11349 if ( options.debug ) {
11350 debugFile->writeCLine (ic);
11353 if(!options.noCcodeInAsm) {
11354 pic16_addpCode2pBlock(pb,
11355 pic16_newpCodeCSource(ic->lineno, ic->filename,
11356 printCLine(ic->filename, ic->lineno)));
11362 if(options.iCodeInAsm) {
11364 /* insert here code to print iCode as comment */
11365 l = Safe_strdup(printILine(ic));
11366 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11369 /* if the result is marked as
11370 spilt and rematerializable or code for
11371 this has already been generated then
11373 if (resultRemat(ic) || ic->generated )
11376 /* depending on the operation */
11395 /* IPOP happens only when trying to restore a
11396 spilt live range, if there is an ifx statement
11397 following this pop then the if statement might
11398 be using some of the registers being popped which
11399 would destroy the contents of the register so
11400 we need to check for this condition and handle it */
11402 ic->next->op == IFX &&
11403 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
11404 genIfx (ic->next,ic);
11422 genEndFunction (ic);
11438 pic16_genPlus (ic) ;
11442 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11443 pic16_genMinus (ic);
11459 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
11463 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11470 /* note these two are xlated by algebraic equivalence
11471 during parsing SDCC.y */
11472 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11473 "got '>=' or '<=' shouldn't have come here");
11477 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11489 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11493 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11497 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11521 genRightShift (ic);
11524 case GET_VALUE_AT_ADDRESS:
11529 if (POINTER_SET(ic))
11556 addSet(&_G.sendSet,ic);
11559 case DUMMY_READ_VOLATILE:
11569 /* now we are ready to call the
11570 peep hole optimizer */
11571 if (!options.nopeep) {
11572 peepHole (&lineHead);
11574 /* now do the actual printing */
11575 printLine (lineHead,codeOutFile);
11578 DFPRINTF((stderr,"printing pBlock\n\n"));
11579 pic16_printpBlock(stdout,pb);