1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic16
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002)
9 - Vangelis Rokas vrokas@otenet.gr (2003)
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 In other words, you are welcome to use, share and improve this program.
26 You are forbidden to forbid anyone else to use, share and improve
27 what you give them. Help stamp out software-hoarding!
30 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
31 Made everything static
32 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
50 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 void pic16_genMult8X8_8 (operand *, operand *,operand *);
53 void pic16_genMult16X16_16(operand *, operand *, operand *);
54 void pic16_genMult32X32_32(operand *, operand *, operand *);
55 pCode *pic16_AssembleLine(char *line, int peeps);
56 extern void pic16_printpBlock(FILE *of, pBlock *pb);
57 static asmop *newAsmop (short type);
58 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
59 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
60 static void mov2w (asmop *aop, int offset);
61 static int aopIdx (asmop *aop, int offset);
63 static int labelOffset=0;
64 extern int pic16_debug_verbose;
65 static int optimized_for_speed = 0;
71 /* max_key keeps track of the largest label number used in
72 a function. This is then used to adjust the label offset
73 for the next function.
76 static int GpsuedoStkPtr=0;
78 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
79 unsigned int pic16aopLiteral (value *val, int offset);
80 const char *pic16_AopType(short type);
81 static iCode *ifxForOp ( operand *op, iCode *ic );
83 void pic16_pushpCodeOp(pCodeOp *pcop);
84 void pic16_poppCodeOp(pCodeOp *pcop);
86 static bool is_LitOp(operand *op);
87 static bool is_LitAOp(asmop *aop);
90 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
92 /* this is the down and dirty file with all kinds of
93 kludgy & hacky stuff. This is what it is all about
94 CODE GENERATION for a specific MCU . some of the
95 routines may be reusable, will have to see */
97 static char *zero = "#0x00";
98 static char *one = "#0x01";
99 static char *spname = "sp";
103 * Function return value policy (MSB-->LSB):
105 * 16 bits -> PRODL:WREG
106 * 24 bits -> PRODH:PRODL:WREG
107 * 32 bits -> FSR0L:PRODH:PRODL:WREG
108 * >32 bits -> on stack, and FSR0 points to the beginning
113 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
114 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
115 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
116 static char **fReturn = fReturnpic16;
118 static char *accUse[] = {"WREG"};
120 //static short rbank = -1;
133 /* Resolved ifx structure. This structure stores information
134 about an iCode ifx that makes it easier to generate code.
136 typedef struct resolvedIfx {
137 symbol *lbl; /* pointer to a label */
138 int condition; /* true or false ifx */
139 int generated; /* set true when the code associated with the ifx
143 extern int pic16_ptrRegReq ;
144 extern int pic16_nRegs;
145 extern FILE *codeOutFile;
146 static void saverbank (int, iCode *,bool);
148 static lineNode *lineHead = NULL;
149 static lineNode *lineCurr = NULL;
151 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
152 0xE0, 0xC0, 0x80, 0x00};
153 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
154 0x07, 0x03, 0x01, 0x00};
158 /*-----------------------------------------------------------------*/
159 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
160 /* exponent of 2 is returned, otherwise -1 is */
162 /* note that this is similar to the function `powof2' in SDCCsymt */
166 /*-----------------------------------------------------------------*/
167 static int my_powof2 (unsigned long num)
170 if( (num & (num-1)) == 0) {
183 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
185 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
187 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
188 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
189 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
190 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
191 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
192 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
193 ((result) ? AOP_SIZE(result) : 0));
196 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
199 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
201 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
202 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
203 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
204 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
205 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
206 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
210 void pic16_emitpcomment (char *fmt, ...)
213 char lb[INITIAL_INLINEASM];
219 vsprintf(lb+1,fmt,ap);
221 while (isspace(*lbp)) lbp++;
224 lineCurr = (lineCurr ?
225 connectLine(lineCurr,newLineNode(lb)) :
226 (lineHead = newLineNode(lb)));
227 lineCurr->isInline = _G.inLine;
228 lineCurr->isDebug = _G.debugLine;
230 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
233 // fprintf(stderr, "%s\n", lb);
236 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
239 char lb[INITIAL_INLINEASM];
242 if(!pic16_debug_verbose)
249 sprintf(lb,"%s\t",inst);
251 sprintf(lb,"%s",inst);
252 vsprintf(lb+(strlen(lb)),fmt,ap);
256 while (isspace(*lbp)) lbp++;
259 lineCurr = (lineCurr ?
260 connectLine(lineCurr,newLineNode(lb)) :
261 (lineHead = newLineNode(lb)));
262 lineCurr->isInline = _G.inLine;
263 lineCurr->isDebug = _G.debugLine;
265 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
268 // fprintf(stderr, "%s\n", lb);
271 void pic16_emitpLabel(int key)
273 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
276 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
280 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
282 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
284 // fprintf(stderr, "%s\n", pcop->name);
287 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
290 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
296 #define pic16_emitcode DEBUGpic16_emitcode
298 /*-----------------------------------------------------------------*/
299 /* pic16_emitcode - writes the code into a file : for now it is simple */
300 /*-----------------------------------------------------------------*/
301 void pic16_emitcode (char *inst,char *fmt, ...)
304 char lb[INITIAL_INLINEASM];
311 sprintf(lb,"%s\t",inst);
313 sprintf(lb,"%s",inst);
314 vsprintf(lb+(strlen(lb)),fmt,ap);
318 while (isspace(*lbp)) lbp++;
321 lineCurr = (lineCurr ?
322 connectLine(lineCurr,newLineNode(lb)) :
323 (lineHead = newLineNode(lb)));
324 lineCurr->isInline = _G.inLine;
325 lineCurr->isDebug = _G.debugLine;
327 // VR fprintf(stderr, "lb = <%s>\n", lbp);
329 // if(pic16_debug_verbose)
330 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
337 /*-----------------------------------------------------------------*/
338 /* pic16_emitDebuggerSymbol - associate the current code location */
339 /* with a debugger symbol */
340 /*-----------------------------------------------------------------*/
342 pic16_emitDebuggerSymbol (char * debugSym)
345 pic16_emitcode (";", "%s ==.", debugSym);
350 /*-----------------------------------------------------------------*/
351 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
352 /*-----------------------------------------------------------------*/
353 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
355 bool r0iu = FALSE , r1iu = FALSE;
356 bool r0ou = FALSE , r1ou = FALSE;
358 //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
360 /* the logic: if r0 & r1 used in the instruction
361 then we are in trouble otherwise */
363 /* first check if r0 & r1 are used by this
364 instruction, in which case we are in trouble */
365 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
366 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
371 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
372 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
374 /* if no usage of r0 then return it */
375 if (!r0iu && !r0ou) {
376 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
377 (*aopp)->type = AOP_R0;
379 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
382 /* if no usage of r1 then return it */
383 if (!r1iu && !r1ou) {
384 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
385 (*aopp)->type = AOP_R1;
387 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
390 /* now we know they both have usage */
391 /* if r0 not used in this instruction */
393 /* push it if not already pushed */
395 //pic16_emitcode ("push","%s",
396 // pic16_regWithIdx(R0_IDX)->dname);
400 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
401 (*aopp)->type = AOP_R0;
403 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
406 /* if r1 not used then */
409 /* push it if not already pushed */
411 //pic16_emitcode ("push","%s",
412 // pic16_regWithIdx(R1_IDX)->dname);
416 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
417 (*aopp)->type = AOP_R1;
418 return pic16_regWithIdx(R1_IDX);
422 /* I said end of world but not quite end of world yet */
423 /* if this is a result then we can push it on the stack*/
425 (*aopp)->type = AOP_STK;
429 /* other wise this is true end of the world */
430 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
431 "getFreePtr should never reach here");
435 /*-----------------------------------------------------------------*/
436 /* newAsmop - creates a new asmOp */
437 /*-----------------------------------------------------------------*/
438 static asmop *newAsmop (short type)
442 aop = Safe_calloc(1,sizeof(asmop));
447 static void genSetDPTR(int n)
451 pic16_emitcode(";", "Select standard DPTR");
452 pic16_emitcode("mov", "dps, #0x00");
456 pic16_emitcode(";", "Select alternate DPTR");
457 pic16_emitcode("mov", "dps, #0x01");
461 /*-----------------------------------------------------------------*/
462 /* resolveIfx - converts an iCode ifx into a form more useful for */
463 /* generating code */
464 /*-----------------------------------------------------------------*/
465 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
468 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
474 resIfx->condition = 1; /* assume that the ifx is true */
475 resIfx->generated = 0; /* indicate that the ifx has not been used */
478 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
481 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
482 __FUNCTION__,__LINE__,resIfx->lbl->key);
487 resIfx->lbl = IC_TRUE(ifx);
489 resIfx->lbl = IC_FALSE(ifx);
490 resIfx->condition = 0;
495 DEBUGpic16_emitcode("; ***","ifx true is non-null");
497 DEBUGpic16_emitcode("; ***","ifx false is non-null");
501 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
505 /*-----------------------------------------------------------------*/
506 /* pointerCode - returns the code for a pointer type */
507 /*-----------------------------------------------------------------*/
508 static int pointerCode (sym_link *etype)
511 return PTR_TYPE(SPEC_OCLS(etype));
516 /*-----------------------------------------------------------------*/
517 /* aopForSym - for a true symbol */
518 /*-----------------------------------------------------------------*/
519 static asmop *aopForSym (iCode *ic, operand *op, bool result)
521 symbol *sym=OP_SYMBOL(op);
523 memmap *space= SPEC_OCLS(sym->etype);
525 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
527 // sym = OP_SYMBOL(op);
529 /* if already has one */
531 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
535 /* if symbol was initially placed onStack then we must re-place it
536 * to direct memory, since pic16 does not have a specific stack */
539 SPEC_OCLS( sym->etype ) = data;
545 /* assign depending on the storage class */
546 /* if it is on the stack or indirectly addressable */
547 /* space we need to assign either r0 or r1 to it */
548 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
550 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
551 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
553 sym->aop = aop = newAsmop(0);
554 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
555 aop->size = getSize(sym->type);
557 /* now assign the address of the variable to
558 the pointer register */
559 if (aop->type != AOP_STK) {
563 pic16_emitcode("push","acc");
565 pic16_emitcode("mov","a,_bp");
566 pic16_emitcode("add","a,#0x%02x",
568 ((char)(sym->stack - _G.nRegsSaved )) :
569 ((char)sym->stack)) & 0xff);
570 pic16_emitcode("mov","%s,a",
571 aop->aopu.aop_ptr->name);
574 pic16_emitcode("pop","acc");
576 pic16_emitcode("mov","%s,#%s",
577 aop->aopu.aop_ptr->name,
579 aop->paged = space->paged;
581 aop->aopu.aop_stk = sym->stack;
586 if (sym->onStack && options.stack10bit)
588 /* It's on the 10 bit stack, which is located in
592 //DEBUGpic16_emitcode(";","%d",__LINE__);
595 pic16_emitcode("push","acc");
597 pic16_emitcode("mov","a,_bp");
598 pic16_emitcode("add","a,#0x%02x",
600 ((char)(sym->stack - _G.nRegsSaved )) :
601 ((char)sym->stack)) & 0xff);
604 pic16_emitcode ("mov","dpx1,#0x40");
605 pic16_emitcode ("mov","dph1,#0x00");
606 pic16_emitcode ("mov","dpl1, a");
610 pic16_emitcode("pop","acc");
612 sym->aop = aop = newAsmop(AOP_DPTR2);
613 aop->size = getSize(sym->type);
617 //DEBUGpic16_emitcode(";","%d",__LINE__);
618 /* if in bit space */
619 if (IN_BITSPACE(space)) {
620 sym->aop = aop = newAsmop (AOP_CRY);
621 aop->aopu.aop_dir = sym->rname ;
622 aop->size = getSize(sym->type);
623 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
626 /* if it is in direct space */
627 if (IN_DIRSPACE(space)) {
628 sym->aop = aop = newAsmop (AOP_DIR);
629 aop->aopu.aop_dir = sym->rname ;
630 aop->size = getSize(sym->type);
631 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
632 pic16_allocDirReg( IC_LEFT(ic) );
637 /* special case for a function */
638 if (IS_FUNC(sym->type)) {
639 sym->aop = aop = newAsmop(AOP_IMMD);
640 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
641 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
642 strcpy(aop->aopu.aop_immd,sym->rname);
643 aop->size = FPTRSIZE;
644 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
650 /* only remaining is far space */
651 /* in which case DPTR gets the address */
652 sym->aop = aop = newAsmop(AOP_PCODE);
654 /* change the next if to 1 to revert to good old immediate code */
655 if(IN_CODESPACE(space)) {
656 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
657 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
658 PCOI(aop->aopu.pcop)->index = 0;
660 /* try to allocate via direct register */
661 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
662 // aop->size = getSize( sym->type );
665 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
666 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
669 if(!pic16_allocDirReg (IC_LEFT(ic)))
673 if(IN_DIRSPACE( space ))
675 else if(IN_CODESPACE( space ))
676 aop->size = FPTRSIZE;
677 else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
678 else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
683 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
685 /* if it is in code space */
686 if (IN_CODESPACE(space))
692 /*-----------------------------------------------------------------*/
693 /* aopForRemat - rematerialzes an object */
694 /*-----------------------------------------------------------------*/
695 static asmop *aopForRemat (operand *op) // x symbol *sym)
697 symbol *sym = OP_SYMBOL(op);
698 iCode *ic = NULL, *oldic;
699 asmop *aop = newAsmop(AOP_PCODE);
705 ic = sym->rematiCode;
707 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
709 if(IS_OP_POINTER(op)) {
710 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
716 // pic16_emitpcomment("ic: %s\n", printILine(ic));
719 val += (int) operandLitValue(IC_RIGHT(ic));
720 } else if (ic->op == '-') {
721 val -= (int) operandLitValue(IC_RIGHT(ic));
725 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
728 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
730 if(!op->isaddr)viaimmd++; else viaimmd=0;
732 /* set the following if to 1 to revert to good old immediate code */
733 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
736 DEBUGpic16_emitcode("%s:%d immediate", __FILE__, __LINE__);
738 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
741 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
743 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
746 PCOI(aop->aopu.pcop)->index = val;
748 DEBUGpic16_emitcode("%s:%d dir", __FILE__, __LINE__);
750 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
751 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
752 // aop->size = AOP_SIZE( IC_LEFT(ic) );
756 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
757 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
759 val, IS_PTR_CONST(operandType(op)));
761 val, IS_CODEPTR(operandType(op)));
764 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
766 pic16_allocDirReg (IC_LEFT(ic));
768 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
774 static int aopIdx (asmop *aop, int offset)
779 if(aop->type != AOP_REG)
782 return aop->aopu.aop_reg[offset]->rIdx;
785 /*-----------------------------------------------------------------*/
786 /* regsInCommon - two operands have some registers in common */
787 /*-----------------------------------------------------------------*/
788 static bool regsInCommon (operand *op1, operand *op2)
793 /* if they have registers in common */
794 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
797 sym1 = OP_SYMBOL(op1);
798 sym2 = OP_SYMBOL(op2);
800 if (sym1->nRegs == 0 || sym2->nRegs == 0)
803 for (i = 0 ; i < sym1->nRegs ; i++) {
808 for (j = 0 ; j < sym2->nRegs ;j++ ) {
812 if (sym2->regs[j] == sym1->regs[i])
820 /*-----------------------------------------------------------------*/
821 /* operandsEqu - equivalent */
822 /*-----------------------------------------------------------------*/
823 static bool operandsEqu ( operand *op1, operand *op2)
827 /* if they not symbols */
828 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
831 sym1 = OP_SYMBOL(op1);
832 sym2 = OP_SYMBOL(op2);
834 /* if both are itemps & one is spilt
835 and the other is not then false */
836 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
837 sym1->isspilt != sym2->isspilt )
840 /* if they are the same */
844 if (strcmp(sym1->rname,sym2->rname) == 0)
848 /* if left is a tmp & right is not */
852 (sym1->usl.spillLoc == sym2))
859 (sym2->usl.spillLoc == sym1))
865 /*-----------------------------------------------------------------*/
866 /* pic16_sameRegs - two asmops have the same registers */
867 /*-----------------------------------------------------------------*/
868 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
875 if (aop1->type != AOP_REG ||
876 aop2->type != AOP_REG )
879 if (aop1->size != aop2->size )
882 for (i = 0 ; i < aop1->size ; i++ )
883 if (aop1->aopu.aop_reg[i] !=
884 aop2->aopu.aop_reg[i] )
890 /*-----------------------------------------------------------------*/
891 /* pic16_aopOp - allocates an asmop for an operand : */
892 /*-----------------------------------------------------------------*/
893 void pic16_aopOp (operand *op, iCode *ic, bool result)
902 // DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
904 /* if this a literal */
905 if (IS_OP_LITERAL(op)) {
906 op->aop = aop = newAsmop(AOP_LIT);
907 aop->aopu.aop_lit = op->operand.valOperand;
908 aop->size = getSize(operandType(op));
913 sym_link *type = operandType(op);
915 if(IS_PTR_CONST(type))
919 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
922 /* if already has a asmop then continue */
926 /* if the underlying symbol has a aop */
927 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
928 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
929 op->aop = OP_SYMBOL(op)->aop;
933 /* if this is a true symbol */
934 if (IS_TRUE_SYMOP(op)) {
935 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
936 op->aop = aopForSym(ic, op, result);
940 /* this is a temporary : this has
946 e) can be a return use only */
950 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
951 /* if the type is a conditional */
952 if (sym->regType == REG_CND) {
953 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
958 /* if it is spilt then two situations
960 b) has a spill location */
961 if (sym->isspilt || sym->nRegs == 0) {
963 DEBUGpic16_emitcode(";","%d",__LINE__);
964 /* rematerialize it NOW */
967 sym->aop = op->aop = aop =
969 aop->size = getSize(sym->type);
970 //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
977 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
978 aop->size = getSize(sym->type);
979 for ( i = 0 ; i < 1 ; i++ ) {
980 aop->aopu.aop_str[i] = accUse[i];
981 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
983 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
984 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
992 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
993 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
994 //pic16_allocDirReg (IC_LEFT(ic));
995 aop->size = getSize(sym->type);
1000 aop = op->aop = sym->aop = newAsmop(AOP_STR);
1001 aop->size = getSize(sym->type);
1002 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1003 aop->aopu.aop_str[i] = fReturn[i];
1005 DEBUGpic16_emitcode(";","%d",__LINE__);
1009 /* else spill location */
1010 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1011 /* force a new aop if sizes differ */
1012 sym->usl.spillLoc->aop = NULL;
1014 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1015 __FUNCTION__,__LINE__,
1016 sym->usl.spillLoc->rname,
1017 sym->rname, sym->usl.spillLoc->offset);
1019 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1020 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1021 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1023 sym->usl.spillLoc->offset, op);
1024 aop->size = getSize(sym->type);
1030 sym_link *type = operandType(op);
1032 if(IS_PTR_CONST(type))
1034 if(IS_CODEPTR(type))
1036 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1039 /* must be in a register */
1040 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1041 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1042 aop->size = sym->nRegs;
1043 for ( i = 0 ; i < sym->nRegs ;i++)
1044 aop->aopu.aop_reg[i] = sym->regs[i];
1047 /*-----------------------------------------------------------------*/
1048 /* pic16_freeAsmop - free up the asmop given to an operand */
1049 /*----------------------------------------------------------------*/
1050 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1067 /* depending on the asmop type only three cases need work AOP_RO
1068 , AOP_R1 && AOP_STK */
1070 switch (aop->type) {
1074 pic16_emitcode ("pop","ar0");
1078 bitVectUnSetBit(ic->rUsed,R0_IDX);
1084 pic16_emitcode ("pop","ar1");
1088 bitVectUnSetBit(ic->rUsed,R1_IDX);
1094 int stk = aop->aopu.aop_stk + aop->size;
1095 bitVectUnSetBit(ic->rUsed,R0_IDX);
1096 bitVectUnSetBit(ic->rUsed,R1_IDX);
1098 getFreePtr(ic,&aop,FALSE);
1100 if (options.stack10bit)
1102 /* I'm not sure what to do here yet... */
1105 "*** Warning: probably generating bad code for "
1106 "10 bit stack mode.\n");
1110 pic16_emitcode ("mov","a,_bp");
1111 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1112 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1114 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1118 pic16_emitcode("pop","acc");
1119 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1121 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1124 pic16_freeAsmop(op,NULL,ic,TRUE);
1126 pic16_emitcode("pop","ar0");
1131 pic16_emitcode("pop","ar1");
1139 /* all other cases just dealloc */
1143 OP_SYMBOL(op)->aop = NULL;
1144 /* if the symbol has a spill */
1146 SPIL_LOC(op)->aop = NULL;
1151 /*-----------------------------------------------------------------*/
1152 /* pic16_aopGet - for fetching value of the aop */
1153 /*-----------------------------------------------------------------*/
1154 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1159 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1161 /* offset is greater than size then zero */
1162 if (offset > (aop->size - 1) &&
1163 aop->type != AOP_LIT)
1166 /* depending on type */
1167 switch (aop->type) {
1171 DEBUGpic16_emitcode(";","%d",__LINE__);
1172 /* if we need to increment it */
1173 while (offset > aop->coff) {
1174 pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);
1178 while (offset < aop->coff) {
1179 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1183 aop->coff = offset ;
1185 pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1186 return (dname ? "acc" : "a");
1188 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1189 rs = Safe_calloc(1,strlen(s)+1);
1195 DEBUGpic16_emitcode(";","%d",__LINE__);
1196 if (aop->type == AOP_DPTR2)
1201 while (offset > aop->coff) {
1202 pic16_emitcode ("inc","dptr");
1206 while (offset < aop->coff) {
1207 pic16_emitcode("lcall","__decdptr");
1213 pic16_emitcode("clr","a");
1214 pic16_emitcode("movc","a,@a+dptr");
1217 pic16_emitcode("movx","a,@dptr");
1220 if (aop->type == AOP_DPTR2)
1225 return (dname ? "acc" : "a");
1230 sprintf (s,"%s",aop->aopu.aop_immd);
1233 sprintf(s,"(%s >> %d)",
1238 aop->aopu.aop_immd);
1239 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1240 rs = Safe_calloc(1,strlen(s)+1);
1246 sprintf(s,"(%s + %d)",
1249 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1251 sprintf(s,"%s",aop->aopu.aop_dir);
1252 rs = Safe_calloc(1,strlen(s)+1);
1258 // return aop->aopu.aop_reg[offset]->dname;
1260 return aop->aopu.aop_reg[offset]->name;
1263 //pic16_emitcode(";","%d",__LINE__);
1264 return aop->aopu.aop_dir;
1267 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1268 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1270 return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1273 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1274 rs = Safe_calloc(1,strlen(s)+1);
1279 aop->coff = offset ;
1280 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1283 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1285 return aop->aopu.aop_str[offset];
1289 pCodeOp *pcop = aop->aopu.pcop;
1290 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1292 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1293 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1294 sprintf(s,"%s", pcop->name);
1296 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1299 rs = Safe_calloc(1,strlen(s)+1);
1305 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1306 "aopget got unsupported aop->type");
1311 /*-----------------------------------------------------------------*/
1312 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1313 /*-----------------------------------------------------------------*/
1314 pCodeOp *pic16_popGetTempReg(void)
1319 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1324 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1325 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1326 PCOR(pcop)->r->wasUsed=1;
1327 PCOR(pcop)->r->isFree=0;
1329 /* push value on stack */
1330 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1338 /*-----------------------------------------------------------------*/
1339 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1340 /*-----------------------------------------------------------------*/
1341 void pic16_popReleaseTempReg(pCodeOp *pcop)
1343 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1345 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1346 PCOR(pcop)->r->isFree = 1;
1348 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1351 /*-----------------------------------------------------------------*/
1352 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1353 /*-----------------------------------------------------------------*/
1354 pCodeOp *pic16_popGetLabel(unsigned int key)
1357 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1362 return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1365 /*-----------------------------------------------------------------*/
1366 /* pic16_popCopyReg - copy a pcode operator */
1367 /*-----------------------------------------------------------------*/
1368 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1372 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1373 pcor->pcop.type = pc->pcop.type;
1375 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1376 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1378 pcor->pcop.name = NULL;
1381 pcor->rIdx = pc->rIdx;
1384 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1389 /*-----------------------------------------------------------------*/
1390 /* pic16_popGetLit - asm operator to pcode operator conversion */
1391 /*-----------------------------------------------------------------*/
1392 pCodeOp *pic16_popGetLit(unsigned int lit)
1394 return pic16_newpCodeOpLit(lit);
1397 /*-----------------------------------------------------------------*/
1398 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1399 /*-----------------------------------------------------------------*/
1400 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1402 return pic16_newpCodeOpLit2(lit, arg2);
1406 /*-----------------------------------------------------------------*/
1407 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1408 /*-----------------------------------------------------------------*/
1409 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1411 return pic16_newpCodeOpImmd(name, offset,index, 0);
1415 /*-----------------------------------------------------------------*/
1416 /* pic16_popGet - asm operator to pcode operator conversion */
1417 /*-----------------------------------------------------------------*/
1418 pCodeOp *pic16_popGetWithString(char *str)
1424 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1428 pcop = pic16_newpCodeOp(str,PO_STR);
1433 /*-----------------------------------------------------------------*/
1434 /* pic16_popRegFromString - */
1435 /*-----------------------------------------------------------------*/
1436 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1439 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1440 pcop->type = PO_DIR;
1442 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1443 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1448 pcop->name = Safe_calloc(1,strlen(str)+1);
1449 strcpy(pcop->name,str);
1451 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1453 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1454 if(PCOR(pcop)->r == NULL) {
1455 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1456 // __FUNCTION__, __LINE__, str, size, offset);
1457 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1459 //fprintf(stderr, "allocating new register -> %s\n", str);
1461 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1463 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d",__LINE__,pcop->name,size,offset);
1465 PCOR(pcop)->instance = offset;
1470 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1474 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1476 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1477 PCOR(pcop)->rIdx = rIdx;
1478 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1479 PCOR(pcop)->r->isFree = 0;
1480 PCOR(pcop)->r->wasUsed = 1;
1482 pcop->type = PCOR(pcop)->r->pc_type;
1487 /*---------------------------------------------------------------------------------*/
1488 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1490 /*---------------------------------------------------------------------------------*/
1491 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1496 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1498 /* comment the following check, so errors to throw up */
1499 // if(!pcop2)return NULL;
1501 temp = pic16_popGet(aop_dst, offset);
1502 pcop2->pcop2 = temp;
1509 /*--------------------------------------------------------------------------------.-*/
1510 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1511 /* VR 030601 , adapted by Hans Dorn */
1512 /*--------------------------------------------------------------------------------.-*/
1513 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1517 pcop2 = (pCodeOpReg2 *)src;
1525 /*---------------------------------------------------------------------------------*/
1526 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1527 /* movff instruction */
1528 /*---------------------------------------------------------------------------------*/
1529 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1534 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1535 pcop2->pcop2 = pic16_popCopyReg(dst);
1537 /* the pCodeOp may be already allocated */
1538 pcop2 = (pCodeOpReg2 *)(src);
1539 pcop2->pcop2 = (pCodeOp *)(dst);
1546 /*-----------------------------------------------------------------*/
1547 /* pic16_popGet - asm operator to pcode operator conversion */
1548 /*-----------------------------------------------------------------*/
1549 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1551 //char *s = buffer ;
1555 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1556 /* offset is greater than
1559 // if (offset > (aop->size - 1) &&
1560 // aop->type != AOP_LIT)
1561 // return NULL; //zero;
1563 /* depending on type */
1564 switch (aop->type) {
1570 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1571 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1578 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1579 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1583 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1585 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1587 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1589 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1590 PCOR(pcop)->rIdx = rIdx;
1591 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1592 PCOR(pcop)->r->wasUsed=1;
1593 PCOR(pcop)->r->isFree=0;
1595 PCOR(pcop)->instance = offset;
1596 pcop->type = PCOR(pcop)->r->pc_type;
1597 // rs = aop->aopu.aop_reg[offset]->name;
1598 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1602 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1603 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1609 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1610 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1614 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1616 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1618 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1619 PCOR(pcop)->rIdx = rIdx;
1620 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1621 PCOR(pcop)->r->wasUsed=1;
1622 PCOR(pcop)->r->isFree=0;
1624 PCOR(pcop)->instance = offset;
1625 pcop->type = PCOR(pcop)->r->pc_type;
1626 rs = aop->aopu.aop_reg[offset]->name;
1627 DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1632 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1634 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1635 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1636 //if(PCOR(pcop)->r == NULL)
1637 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1641 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1642 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1645 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1646 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1649 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1650 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1651 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1652 pcop->type = PCOR(pcop)->r->pc_type;
1653 pcop->name = PCOR(pcop)->r->name;
1659 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1661 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1662 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1664 switch( aop->aopu.pcop->type ) {
1665 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1666 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1668 assert( 0 ); /* should never reach here */;
1671 PCOI(pcop)->offset = offset;
1676 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1677 "pic16_popGet got unsupported aop->type");
1680 /*-----------------------------------------------------------------*/
1681 /* pic16_aopPut - puts a string for a aop */
1682 /*-----------------------------------------------------------------*/
1683 void pic16_aopPut (asmop *aop, char *s, int offset)
1688 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1690 if (aop->size && offset > ( aop->size - 1)) {
1691 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1692 "pic16_aopPut got offset > aop->size");
1696 /* will assign value to value */
1697 /* depending on where it is ofcourse */
1698 switch (aop->type) {
1701 sprintf(d,"(%s + %d)",
1702 aop->aopu.aop_dir,offset);
1703 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1706 sprintf(d,"%s",aop->aopu.aop_dir);
1709 DEBUGpic16_emitcode(";","%d",__LINE__);
1711 pic16_emitcode("movf","%s,w",s);
1712 pic16_emitcode("movwf","%s",d);
1715 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1716 if(offset >= aop->size) {
1717 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1720 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1723 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1730 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1731 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1734 strcmp(s,"r0") == 0 ||
1735 strcmp(s,"r1") == 0 ||
1736 strcmp(s,"r2") == 0 ||
1737 strcmp(s,"r3") == 0 ||
1738 strcmp(s,"r4") == 0 ||
1739 strcmp(s,"r5") == 0 ||
1740 strcmp(s,"r6") == 0 ||
1741 strcmp(s,"r7") == 0 )
1742 pic16_emitcode("mov","%s,%s ; %d",
1743 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1747 if(strcmp(s,"W")==0 )
1748 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
1750 pic16_emitcode("movwf","%s",
1751 aop->aopu.aop_reg[offset]->name);
1753 if(strcmp(s,zero)==0) {
1754 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1756 } else if(strcmp(s,"W")==0) {
1757 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1758 pcop->type = PO_GPR_REGISTER;
1760 PCOR(pcop)->rIdx = -1;
1761 PCOR(pcop)->r = NULL;
1763 DEBUGpic16_emitcode(";","%d",__LINE__);
1764 pcop->name = Safe_strdup(s);
1765 pic16_emitpcode(POC_MOVFW,pcop);
1766 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1767 } else if(strcmp(s,one)==0) {
1768 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1769 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1771 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1779 if (aop->type == AOP_DPTR2)
1785 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1786 "pic16_aopPut writting to code space");
1790 while (offset > aop->coff) {
1792 pic16_emitcode ("inc","dptr");
1795 while (offset < aop->coff) {
1797 pic16_emitcode("lcall","__decdptr");
1802 /* if not in accumulater */
1805 pic16_emitcode ("movx","@dptr,a");
1807 if (aop->type == AOP_DPTR2)
1815 while (offset > aop->coff) {
1817 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1819 while (offset < aop->coff) {
1821 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1827 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1832 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1834 if (strcmp(s,"r0") == 0 ||
1835 strcmp(s,"r1") == 0 ||
1836 strcmp(s,"r2") == 0 ||
1837 strcmp(s,"r3") == 0 ||
1838 strcmp(s,"r4") == 0 ||
1839 strcmp(s,"r5") == 0 ||
1840 strcmp(s,"r6") == 0 ||
1841 strcmp(s,"r7") == 0 ) {
1843 sprintf(buffer,"a%s",s);
1844 pic16_emitcode("mov","@%s,%s",
1845 aop->aopu.aop_ptr->name,buffer);
1847 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1852 if (strcmp(s,"a") == 0)
1853 pic16_emitcode("push","acc");
1855 pic16_emitcode("push","%s",s);
1860 /* if bit variable */
1861 if (!aop->aopu.aop_dir) {
1862 pic16_emitcode("clr","a");
1863 pic16_emitcode("rlc","a");
1866 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1869 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1872 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1874 lbl = newiTempLabel(NULL);
1876 if (strcmp(s,"a")) {
1879 pic16_emitcode("clr","c");
1880 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1881 pic16_emitcode("cpl","c");
1882 pic16_emitcode("","%05d_DS_:",lbl->key+100);
1883 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1890 if (strcmp(aop->aopu.aop_str[offset],s))
1891 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1896 if (!offset && (strcmp(s,"acc") == 0))
1899 if (strcmp(aop->aopu.aop_str[offset],s))
1900 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1904 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1905 "pic16_aopPut got unsupported aop->type");
1911 /*-----------------------------------------------------------------*/
1912 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1913 /*-----------------------------------------------------------------*/
1914 static void mov2w (asmop *aop, int offset)
1920 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1923 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1925 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1930 /* push pcop into stack */
1931 void pic16_pushpCodeOp(pCodeOp *pcop)
1933 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1934 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1937 /* pop pcop from stack */
1938 void pic16_poppCodeOp(pCodeOp *pcop)
1940 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1944 /*-----------------------------------------------------------------*/
1945 /* pushw - pushes wreg to stack */
1946 /*-----------------------------------------------------------------*/
1949 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1950 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1954 /*-----------------------------------------------------------------*/
1955 /* pushaop - pushes aop to stack */
1956 /*-----------------------------------------------------------------*/
1957 void pushaop(asmop *aop, int offset)
1959 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1960 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1963 /*-----------------------------------------------------------------*/
1964 /* popaop - pops aop from stack */
1965 /*-----------------------------------------------------------------*/
1966 void popaop(asmop *aop, int offset)
1968 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
1969 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1972 void popaopidx(asmop *aop, int offset, int index)
1976 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1978 if(STACK_MODEL_LARGE)ofs++;
1980 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1981 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1984 /*-----------------------------------------------------------------*/
1985 /* reAdjustPreg - points a register back to where it should */
1986 /*-----------------------------------------------------------------*/
1987 static void reAdjustPreg (asmop *aop)
1991 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1993 if ((size = aop->size) <= 1)
1996 switch (aop->type) {
2000 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2004 if (aop->type == AOP_DPTR2)
2010 pic16_emitcode("lcall","__decdptr");
2013 if (aop->type == AOP_DPTR2)
2025 /*-----------------------------------------------------------------*/
2026 /* opIsGptr: returns non-zero if the passed operand is */
2027 /* a generic pointer type. */
2028 /*-----------------------------------------------------------------*/
2029 static int opIsGptr(operand *op)
2031 sym_link *type = operandType(op);
2033 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2034 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2042 /*-----------------------------------------------------------------*/
2043 /* pic16_getDataSize - get the operand data size */
2044 /*-----------------------------------------------------------------*/
2045 int pic16_getDataSize(operand *op)
2047 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2050 return AOP_SIZE(op);
2052 // tsd- in the pic port, the genptr size is 1, so this code here
2053 // fails. ( in the 8051 port, the size was 4).
2056 size = AOP_SIZE(op);
2057 if (size == GPTRSIZE)
2059 sym_link *type = operandType(op);
2060 if (IS_GENPTR(type))
2062 /* generic pointer; arithmetic operations
2063 * should ignore the high byte (pointer type).
2066 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2073 /*-----------------------------------------------------------------*/
2074 /* pic16_outAcc - output Acc */
2075 /*-----------------------------------------------------------------*/
2076 void pic16_outAcc(operand *result)
2079 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2080 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2083 size = pic16_getDataSize(result);
2085 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2088 /* unsigned or positive */
2090 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2095 /*-----------------------------------------------------------------*/
2096 /* pic16_outBitC - output a bit C */
2097 /* Move to result the value of Carry flag -- VR */
2098 /*-----------------------------------------------------------------*/
2099 void pic16_outBitC(operand *result)
2103 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2104 /* if the result is bit */
2105 if (AOP_TYPE(result) == AOP_CRY) {
2106 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2107 pic16_aopPut(AOP(result),"c",0);
2110 i = AOP_SIZE(result);
2112 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2114 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2117 pic16_emitcode("clr","a ; %d", __LINE__);
2118 pic16_emitcode("rlc","a");
2119 pic16_outAcc(result);
2124 /*-----------------------------------------------------------------*/
2125 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2126 /*-----------------------------------------------------------------*/
2127 void pic16_toBoolean(operand *oper)
2129 int size = AOP_SIZE(oper) - 1;
2132 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2134 if ( AOP_TYPE(oper) != AOP_ACC) {
2135 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2138 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2143 #if !defined(GEN_Not)
2144 /*-----------------------------------------------------------------*/
2145 /* genNot - generate code for ! operation */
2146 /*-----------------------------------------------------------------*/
2147 static void pic16_genNot (iCode *ic)
2152 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2153 /* assign asmOps to operand & result */
2154 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2155 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2157 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2158 /* if in bit space then a special case */
2159 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2160 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2161 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2162 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2164 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2165 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2166 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2171 size = AOP_SIZE(IC_LEFT(ic));
2173 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2174 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2175 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2178 pic16_toBoolean(IC_LEFT(ic));
2180 tlbl = newiTempLabel(NULL);
2181 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2182 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2183 pic16_outBitC(IC_RESULT(ic));
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);
2193 #if !defined(GEN_Cpl)
2194 /*-----------------------------------------------------------------*/
2195 /* genCpl - generate code for complement */
2196 /*-----------------------------------------------------------------*/
2197 static void pic16_genCpl (iCode *ic)
2203 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2204 /* assign asmOps to operand & result */
2205 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2206 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2208 /* if both are in bit space then
2210 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2211 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2213 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2214 pic16_emitcode("cpl","c");
2215 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2219 size = AOP_SIZE(IC_RESULT(ic));
2222 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2224 pic16_emitcode("cpl","a");
2225 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2227 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2228 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2230 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2231 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2239 /* release the aops */
2240 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2241 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2245 /*-----------------------------------------------------------------*/
2246 /* genUminusFloat - unary minus for floating points */
2247 /*-----------------------------------------------------------------*/
2248 static void genUminusFloat(operand *op,operand *result)
2250 int size ,offset =0 ;
2253 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2254 /* for this we just need to flip the
2255 first it then copy the rest in place */
2256 size = AOP_SIZE(op) - 1;
2257 l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2261 pic16_emitcode("cpl","acc.7");
2262 pic16_aopPut(AOP(result),"a",3);
2265 pic16_aopPut(AOP(result),
2266 pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2272 /*-----------------------------------------------------------------*/
2273 /* genUminus - unary minus code generation */
2274 /*-----------------------------------------------------------------*/
2275 static void genUminus (iCode *ic)
2278 sym_link *optype, *rtype;
2280 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2283 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2284 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2286 /* if both in bit space then special case */
2287 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2288 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2290 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2291 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2292 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2297 optype = operandType(IC_LEFT(ic));
2298 rtype = operandType(IC_RESULT(ic));
2300 /* if float then do float stuff */
2301 if (IS_FLOAT(optype)) {
2302 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2306 /* otherwise subtract from zero by taking the 2's complement */
2307 size = AOP_SIZE(IC_LEFT(ic));
2309 for(i=0; i<size; i++) {
2310 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2311 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)),i));
2313 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2314 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2318 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2319 for(i=1; i<size; i++) {
2321 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2325 /* release the aops */
2326 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2327 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2330 /*-----------------------------------------------------------------*/
2331 /* saveRegisters - will look for a call and save the registers */
2332 /*-----------------------------------------------------------------*/
2333 static void saveRegisters(iCode *lic)
2340 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2342 for (ic = lic ; ic ; ic = ic->next)
2343 if (ic->op == CALL || ic->op == PCALL)
2347 fprintf(stderr,"found parameter push with no function call\n");
2351 /* if the registers have been saved already then
2353 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2356 /* find the registers in use at this time
2357 and push them away to safety */
2358 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2362 if (options.useXstack) {
2363 if (bitVectBitValue(rsave,R0_IDX))
2364 pic16_emitcode("mov","b,r0");
2365 pic16_emitcode("mov","r0,%s",spname);
2366 for (i = 0 ; i < pic16_nRegs ; i++) {
2367 if (bitVectBitValue(rsave,i)) {
2369 pic16_emitcode("mov","a,b");
2371 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2372 pic16_emitcode("movx","@r0,a");
2373 pic16_emitcode("inc","r0");
2376 pic16_emitcode("mov","%s,r0",spname);
2377 if (bitVectBitValue(rsave,R0_IDX))
2378 pic16_emitcode("mov","r0,b");
2380 //for (i = 0 ; i < pic16_nRegs ; i++) {
2381 // if (bitVectBitValue(rsave,i))
2382 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2385 dtype = operandType(IC_LEFT(ic));
2386 if (currFunc && dtype &&
2387 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2388 IFFUNC_ISISR(currFunc->type) &&
2391 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2394 /*-----------------------------------------------------------------*/
2395 /* unsaveRegisters - pop the pushed registers */
2396 /*-----------------------------------------------------------------*/
2397 static void unsaveRegisters (iCode *ic)
2402 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2403 /* find the registers in use at this time
2404 and push them away to safety */
2405 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2408 if (options.useXstack) {
2409 pic16_emitcode("mov","r0,%s",spname);
2410 for (i = pic16_nRegs ; i >= 0 ; i--) {
2411 if (bitVectBitValue(rsave,i)) {
2412 pic16_emitcode("dec","r0");
2413 pic16_emitcode("movx","a,@r0");
2415 pic16_emitcode("mov","b,a");
2417 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2421 pic16_emitcode("mov","%s,r0",spname);
2422 if (bitVectBitValue(rsave,R0_IDX))
2423 pic16_emitcode("mov","r0,b");
2425 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2426 // if (bitVectBitValue(rsave,i))
2427 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2433 /*-----------------------------------------------------------------*/
2435 /*-----------------------------------------------------------------*/
2436 static void pushSide(operand * oper, int size)
2439 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2441 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2442 if (AOP_TYPE(oper) != AOP_REG &&
2443 AOP_TYPE(oper) != AOP_DIR &&
2445 pic16_emitcode("mov","a,%s",l);
2446 pic16_emitcode("push","acc");
2448 pic16_emitcode("push","%s",l);
2453 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2455 // (AOP(left)->aopu.pcop->type == PO_DIR)?
2457 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2458 pic16_emitpcode(POC_MOVFW, src);
2459 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2461 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2462 src, pic16_popGet(AOP(op), offset)));
2467 /*-----------------------------------------------------------------*/
2468 /* assignResultValue - assign results to oper, rescall==1 is */
2469 /* called from genCall() or genPCall() */
2470 /*-----------------------------------------------------------------*/
2471 static void assignResultValue(operand * oper, int rescall)
2473 int size = AOP_SIZE(oper);
2475 DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2476 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2479 /* assign result from a call/pcall function() */
2481 /* function results are stored in a special order,
2482 * see top of file with Function return policy, or manual */
2485 /* 8-bits, result in WREG */
2486 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2489 /* 16-bits, result in PRODL:WREG */
2490 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2494 /* 24-bits, result in PRODH:PRODL:WREG */
2495 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2499 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2500 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2503 /* >32-bits, result on stack, and FSR0 points to beginning.
2504 * Fix stack when done */
2507 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2508 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2510 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2515 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2516 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2517 if(STACK_MODEL_LARGE) {
2519 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2523 if(!GpsuedoStkPtr) {
2524 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2525 /* The last byte in the assignment is in W */
2527 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2532 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2533 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2535 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2541 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2543 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2553 /*-----------------------------------------------------------------*/
2554 /* genIpush - genrate code for pushing this gets a little complex */
2555 /*-----------------------------------------------------------------*/
2556 static void genIpush (iCode *ic)
2559 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2561 int size, offset = 0 ;
2565 /* if this is not a parm push : ie. it is spill push
2566 and spill push is always done on the local stack */
2567 if (!ic->parmPush) {
2569 /* and the item is spilt then do nothing */
2570 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2573 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2574 size = AOP_SIZE(IC_LEFT(ic));
2575 /* push it on the stack */
2577 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2582 pic16_emitcode("push","%s",l);
2587 /* this is a paramter push: in this case we call
2588 the routine to find the call and save those
2589 registers that need to be saved */
2592 /* then do the push */
2593 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2596 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2597 size = AOP_SIZE(IC_LEFT(ic));
2600 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2601 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2602 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2604 pic16_emitcode("mov","a,%s",l);
2605 pic16_emitcode("push","acc");
2607 pic16_emitcode("push","%s",l);
2610 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2614 /*-----------------------------------------------------------------*/
2615 /* genIpop - recover the registers: can happen only for spilling */
2616 /*-----------------------------------------------------------------*/
2617 static void genIpop (iCode *ic)
2619 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2624 /* if the temp was not pushed then */
2625 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2628 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2629 size = AOP_SIZE(IC_LEFT(ic));
2632 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2635 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2639 /*-----------------------------------------------------------------*/
2640 /* unsaverbank - restores the resgister bank from stack */
2641 /*-----------------------------------------------------------------*/
2642 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2644 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2650 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2652 if (options.useXstack) {
2654 r = getFreePtr(ic,&aop,FALSE);
2657 pic16_emitcode("mov","%s,_spx",r->name);
2658 pic16_emitcode("movx","a,@%s",r->name);
2659 pic16_emitcode("mov","psw,a");
2660 pic16_emitcode("dec","%s",r->name);
2663 pic16_emitcode ("pop","psw");
2666 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2667 if (options.useXstack) {
2668 pic16_emitcode("movx","a,@%s",r->name);
2669 //pic16_emitcode("mov","(%s+%d),a",
2670 // regspic16[i].base,8*bank+regspic16[i].offset);
2671 pic16_emitcode("dec","%s",r->name);
2674 pic16_emitcode("pop",""); //"(%s+%d)",
2675 //regspic16[i].base,8*bank); //+regspic16[i].offset);
2678 if (options.useXstack) {
2680 pic16_emitcode("mov","_spx,%s",r->name);
2681 pic16_freeAsmop(NULL,aop,ic,TRUE);
2687 /*-----------------------------------------------------------------*/
2688 /* saverbank - saves an entire register bank on the stack */
2689 /*-----------------------------------------------------------------*/
2690 static void saverbank (int bank, iCode *ic, bool pushPsw)
2692 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2698 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2699 if (options.useXstack) {
2702 r = getFreePtr(ic,&aop,FALSE);
2703 pic16_emitcode("mov","%s,_spx",r->name);
2707 for (i = 0 ; i < pic16_nRegs ;i++) {
2708 if (options.useXstack) {
2709 pic16_emitcode("inc","%s",r->name);
2710 //pic16_emitcode("mov","a,(%s+%d)",
2711 // regspic16[i].base,8*bank+regspic16[i].offset);
2712 pic16_emitcode("movx","@%s,a",r->name);
2714 pic16_emitcode("push","");// "(%s+%d)",
2715 //regspic16[i].base,8*bank+regspic16[i].offset);
2719 if (options.useXstack) {
2720 pic16_emitcode("mov","a,psw");
2721 pic16_emitcode("movx","@%s,a",r->name);
2722 pic16_emitcode("inc","%s",r->name);
2723 pic16_emitcode("mov","_spx,%s",r->name);
2724 pic16_freeAsmop (NULL,aop,ic,TRUE);
2727 pic16_emitcode("push","psw");
2729 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2737 /*-----------------------------------------------------------------*/
2738 /* genCall - generates a call statement */
2739 /*-----------------------------------------------------------------*/
2740 static void genCall (iCode *ic)
2745 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2747 /* if caller saves & we have not saved then */
2751 /* if we are calling a function that is not using
2752 * the same register bank then we need to save the
2753 * destination registers on the stack */
2754 dtype = operandType(IC_LEFT(ic));
2755 if (currFunc && dtype &&
2756 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2757 IFFUNC_ISISR(currFunc->type) &&
2760 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2762 /* if send set is not empty the assign */
2766 /* For the Pic port, there is no data stack.
2767 * So parameters passed to functions are stored
2768 * in registers. (The pCode optimizer will get
2769 * rid of most of these :). */
2771 int psuedoStkPtr=-1;
2772 int firstTimeThruLoop = 1;
2774 _G.sendSet = reverseSet(_G.sendSet);
2776 /* First figure how many parameters are getting passed */
2777 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2778 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2779 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2780 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2783 stackParms = psuedoStkPtr;
2785 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2786 int size, offset = 0;
2788 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2789 size = AOP_SIZE(IC_LEFT(sic));
2792 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2793 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2794 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2796 if(!firstTimeThruLoop) {
2797 /* If this is not the first time we've been through the loop
2798 * then we need to save the parameter in a temporary
2799 * register. The last byte of the last parameter is
2803 --psuedoStkPtr; // sanity check
2806 firstTimeThruLoop=0;
2808 mov2w (AOP(IC_LEFT(sic)), offset);
2811 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2817 pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2818 OP_SYMBOL(IC_LEFT(ic))->rname :
2819 OP_SYMBOL(IC_LEFT(ic))->name));
2822 /* if we need assign a result value */
2823 if ((IS_ITEMP(IC_RESULT(ic)) &&
2824 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2825 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2826 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2829 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2832 assignResultValue(IC_RESULT(ic), 1);
2834 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2835 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2837 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2841 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2842 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2843 if(STACK_MODEL_LARGE) {
2845 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2849 /* adjust the stack for parameters if required */
2850 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2852 if (ic->parmBytes) {
2855 if (ic->parmBytes > 3) {
2856 pic16_emitcode("mov","a,%s",spname);
2857 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2858 pic16_emitcode("mov","%s,a",spname);
2860 for ( i = 0 ; i < ic->parmBytes ;i++)
2861 pic16_emitcode("dec","%s",spname);
2865 /* if register bank was saved then pop them */
2867 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2869 /* if we hade saved some registers then unsave them */
2870 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2871 unsaveRegisters (ic);
2877 /*-----------------------------------------------------------------*/ // patch 14
2878 /* genPcall - generates a call by pointer statement */
2879 /*-----------------------------------------------------------------*/
2881 // new version, created from genCall
2883 static void genPcall (iCode *ic)
2887 symbol *retlbl = newiTempLabel(NULL);
2888 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2890 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2892 /* if caller saves & we have not saved then */
2896 /* if we are calling a function that is not using
2897 * the same register bank then we need to save the
2898 * destination registers on the stack */
2899 dtype = operandType(IC_LEFT(ic));
2900 if (currFunc && dtype &&
2901 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2902 IFFUNC_ISISR(currFunc->type) &&
2905 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2907 /* if send set is not empty the assign */
2911 /* For the Pic port, there is no data stack.
2912 * So parameters passed to functions are stored
2913 * in registers. (The pCode optimizer will get
2914 * rid of most of these :). */
2916 int psuedoStkPtr=-1;
2917 int firstTimeThruLoop = 1;
2919 _G.sendSet = reverseSet(_G.sendSet);
2921 /* First figure how many parameters are getting passed */
2922 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2923 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2924 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2925 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2928 stackParms = psuedoStkPtr;
2930 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2931 int size, offset = 0;
2933 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2934 size = AOP_SIZE(IC_LEFT(sic));
2937 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2938 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2939 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2941 if(!firstTimeThruLoop) {
2942 /* If this is not the first time we've been through the loop
2943 * then we need to save the parameter in a temporary
2944 * register. The last byte of the last parameter is
2948 --psuedoStkPtr; // sanity check
2951 firstTimeThruLoop=0;
2953 mov2w (AOP(IC_LEFT(sic)), offset);
2956 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2961 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2963 // push return address
2964 // push $ on return stack, then replace with retlbl
2966 // Note: retlbl is supplied as dummy operand to PUSH
2967 // This has the nice side effect of keeping the label from being optimized out :o)
2968 pic16_emitpcode(POC_PUSH, pic16_popGetLabel(retlbl->key));
2970 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2971 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2972 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2973 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2974 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2975 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2977 /* make the call by writing the pointer into pc */
2978 // FIXME Disabled writes to PCLATU because of gpsim problems
2980 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
2983 "WARNING: (%s:%d) PCLATU is not written because of gpsim problems\n\
2984 Correct this as soon as gpsim bug is fixed\n", __FILE__, __LINE__);
2987 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
2988 // note: MOVFF to PCL not allowed
2989 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
2990 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2992 /* return address is here: (X) */
2993 pic16_emitpLabel(retlbl->key);
2995 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2998 /* if we need assign a result value */
2999 if ((IS_ITEMP(IC_RESULT(ic)) &&
3000 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3001 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
3002 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3005 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3008 assignResultValue(IC_RESULT(ic), 1);
3010 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3011 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3013 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3017 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3018 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3019 if(STACK_MODEL_LARGE) {
3021 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3025 /* adjust the stack for parameters if required */
3026 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3028 if (ic->parmBytes) {
3031 if (ic->parmBytes > 3) {
3032 pic16_emitcode("mov","a,%s",spname);
3033 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3034 pic16_emitcode("mov","%s,a",spname);
3036 for ( i = 0 ; i < ic->parmBytes ;i++)
3037 pic16_emitcode("dec","%s",spname);
3040 /* if register bank was saved then pop them */
3042 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3044 /* if we hade saved some registers then unsave them */
3045 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3046 unsaveRegisters (ic);
3051 // old version, kept for reference
3053 /*-----------------------------------------------------------------*/
3054 /* genPcall - generates a call by pointer statement */
3055 /*-----------------------------------------------------------------*/
3056 static void genPcall (iCode *ic)
3059 symbol *rlbl = newiTempLabel(NULL);
3062 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3063 /* if caller saves & we have not saved then */
3067 /* if we are calling a function that is not using
3068 the same register bank then we need to save the
3069 destination registers on the stack */
3070 dtype = operandType(IC_LEFT(ic));
3071 if (currFunc && dtype &&
3072 IFFUNC_ISISR(currFunc->type) &&
3073 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3074 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3077 /* push the return address on to the stack */
3078 pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3079 pic16_emitcode("push","acc");
3080 pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3081 pic16_emitcode("push","acc");
3083 if (options.model == MODEL_FLAT24)
3085 pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3086 pic16_emitcode("push","acc");
3089 /* now push the calling address */
3090 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3092 pushSide(IC_LEFT(ic), FPTRSIZE);
3094 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3096 /* if send set is not empty the assign */
3100 for (sic = setFirstItem(_G.sendSet) ; sic ;
3101 sic = setNextItem(_G.sendSet)) {
3102 int size, offset = 0;
3103 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3104 size = AOP_SIZE(IC_LEFT(sic));
3106 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3108 if (strcmp(l,fReturn[offset]))
3109 pic16_emitcode("mov","%s,%s",
3114 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3119 pic16_emitcode("ret","");
3120 pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3123 /* if we need assign a result value */
3124 if ((IS_ITEMP(IC_RESULT(ic)) &&
3125 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3126 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3127 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3130 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3133 assignResultValue(IC_RESULT(ic), 1);
3135 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3138 /* adjust the stack for parameters if
3140 if (ic->parmBytes) {
3142 if (ic->parmBytes > 3) {
3143 pic16_emitcode("mov","a,%s",spname);
3144 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3145 pic16_emitcode("mov","%s,a",spname);
3147 for ( i = 0 ; i < ic->parmBytes ;i++)
3148 pic16_emitcode("dec","%s",spname);
3152 /* if register bank was saved then unsave them */
3153 if (currFunc && dtype &&
3154 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3155 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3157 /* if we hade saved some registers then
3160 unsaveRegisters (ic);
3166 /*-----------------------------------------------------------------*/
3167 /* resultRemat - result is rematerializable */
3168 /*-----------------------------------------------------------------*/
3169 static int resultRemat (iCode *ic)
3171 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3172 if (SKIP_IC(ic) || ic->op == IFX)
3175 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3176 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3177 if (sym->remat && !POINTER_SET(ic))
3184 #if defined(__BORLANDC__) || defined(_MSC_VER)
3185 #define STRCASECMP stricmp
3187 #define STRCASECMP strcasecmp
3191 /*-----------------------------------------------------------------*/
3192 /* inExcludeList - return 1 if the string is in exclude Reg list */
3193 /*-----------------------------------------------------------------*/
3194 static bool inExcludeList(char *s)
3196 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3199 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3200 if (options.excludeRegs[i] &&
3201 STRCASECMP(options.excludeRegs[i],"none") == 0)
3204 for ( i = 0 ; options.excludeRegs[i]; i++) {
3205 if (options.excludeRegs[i] &&
3206 STRCASECMP(s,options.excludeRegs[i]) == 0)
3213 /*-----------------------------------------------------------------*/
3214 /* genFunction - generated code for function entry */
3215 /*-----------------------------------------------------------------*/
3216 static void genFunction (iCode *ic)
3221 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
3223 labelOffset += (max_key+4);
3228 ftype = operandType(IC_LEFT(ic));
3229 sym = OP_SYMBOL(IC_LEFT(ic));
3231 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3232 /* create an absolute section at the interrupt vector:
3233 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3241 sym = OP_SYMBOL( IC_LEFT(ic));
3243 if(interrupts[i]->name
3244 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3251 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3252 __FILE__, __LINE__, sym->name);
3255 _G.interruptvector = found;
3258 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3259 asym = newSymbol(asymname, 0);
3261 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3262 pic16_addpBlock( apb );
3264 pic16_addpCode2pBlock(apb,
3265 pic16_newpCodeCharP(";-----------------------------------------"));
3268 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3270 pic16_addpCode2pBlock(apb,
3271 pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3273 /* mark the end of this tiny function */
3274 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3279 abSym = Safe_calloc(1, sizeof(absSym));
3280 abSym->name = Safe_strdup( asymname );
3282 switch( _G.interruptvector ) {
3283 case 0: abSym->address = 0x000000; break;
3284 case 1: abSym->address = 0x000008; break;
3285 case 2: abSym->address = 0x000018; break;
3288 addSet(&absSymSet, abSym);
3293 /* create the function header */
3294 pic16_emitcode(";","-----------------------------------------");
3295 pic16_emitcode(";"," function %s",sym->name);
3296 pic16_emitcode(";","-----------------------------------------");
3298 pic16_emitcode("","%s:",sym->rname);
3299 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3305 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3306 if(!strcmp(ab->name, sym->name)) {
3307 pic16_pBlockConvert2Absolute(pb);
3314 if(IFFUNC_ISNAKED(ftype)) {
3315 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3319 /* if critical function then turn interrupts off */
3320 if (IFFUNC_ISCRITICAL(ftype))
3321 pic16_emitcode("clr","ea");
3323 /* if this is an interrupt service routine then
3324 * save acc, b, dpl, dph */
3325 if (IFFUNC_ISISR(sym->type)) {
3327 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3328 if(!(_G.interruptvector == 1)) {
3330 /* do not save WREG,STATUS,BSR for high priority interrupts
3331 * because they are stored in the hardware shadow registers already */
3333 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3334 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3335 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3338 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3339 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3340 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3341 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3343 // pic16_pBlockConvert2ISR(pb);
3345 /* if any registers used */
3346 if (sym->regsUsed) {
3347 /* save the registers used */
3348 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3349 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3350 if (bitVectBitValue(sym->regsUsed,i)) {
3351 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3352 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3353 // pic16_regWithIdx(i)->name);
3355 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3361 /* emit code to setup stack frame if user enabled,
3362 * and function is not main() */
3364 // fprintf(stderr, "function name: %s\n", sym->name);
3365 if(strcmp(sym->name, "main")) {
3366 if(/*!options.ommitFramePtr || */sym->regsUsed) {
3367 /* setup the stack frame */
3368 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3369 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3370 if(STACK_MODEL_LARGE)
3371 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3375 /* if callee-save to be used for this function
3376 * then save the registers being used in this function */
3377 // if (IFFUNC_CALLEESAVES(sym->type))
3381 // fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3383 // pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3385 /* if any registers used */
3386 if (sym->regsUsed) {
3387 /* save the registers used */
3388 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3389 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3390 if (bitVectBitValue(sym->regsUsed,i)) {
3392 // fprintf(stderr, "%s:%d function %s uses register %s\n",
3393 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3394 // pic16_regWithIdx(i)->name);
3396 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3398 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3399 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3400 // &pic16_pc_postdec1, 0));
3412 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3414 if (options.useXstack) {
3415 pic16_emitcode("mov","r0,%s",spname);
3416 pic16_emitcode("mov","a,_bp");
3417 pic16_emitcode("movx","@r0,a");
3418 pic16_emitcode("inc","%s",spname);
3420 /* set up the stack */
3421 pic16_emitcode ("push","_bp"); /* save the callers stack */
3423 pic16_emitcode ("mov","_bp,%s",spname);
3426 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3428 /* adjust the stack for the function */
3433 werror(W_STACK_OVERFLOW,sym->name);
3435 if (i > 3 && sym->recvSize < 4) {
3436 pic16_emitcode ("mov","a,sp");
3437 pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3438 pic16_emitcode ("mov","sp,a");
3441 pic16_emitcode("inc","sp");
3445 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3447 pic16_emitcode ("mov","a,_spx");
3448 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3449 pic16_emitcode ("mov","_spx,a");
3454 /*-----------------------------------------------------------------*/
3455 /* genEndFunction - generates epilogue for functions */
3456 /*-----------------------------------------------------------------*/
3457 static void genEndFunction (iCode *ic)
3459 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3461 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3463 if(IFFUNC_ISNAKED(sym->type)) {
3464 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3469 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3471 pic16_emitcode ("mov","%s,_bp",spname);
3475 /* if use external stack but some variables were
3476 added to the local stack then decrement the
3478 if (options.useXstack && sym->stack) {
3479 pic16_emitcode("mov","a,sp");
3480 pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3481 pic16_emitcode("mov","sp,a");
3486 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3487 if (options.useXstack) {
3488 pic16_emitcode("mov","r0,%s",spname);
3489 pic16_emitcode("movx","a,@r0");
3490 pic16_emitcode("mov","_bp,a");
3491 pic16_emitcode("dec","%s",spname);
3495 pic16_emitcode ("pop","_bp");
3500 if (IFFUNC_ISISR(sym->type)) {
3501 /* now we need to restore the registers */
3502 /* if any registers used */
3503 if (sym->regsUsed) {
3506 /* restore registers used */
3507 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3508 for ( i = sym->regsUsed->size; i >= 0; i--) {
3509 if (bitVectBitValue(sym->regsUsed,i)) {
3511 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3512 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3513 // pic16_regWithIdx(i)->name);
3515 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3517 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3518 // &pic16_pc_preinc1,
3519 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3525 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3526 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3527 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3528 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3530 if(!(_G.interruptvector == 1)) {
3531 /* do not restore interrupt vector for WREG,STATUS,BSR
3532 * for high priority interrupt, see genFunction */
3534 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3535 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3536 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3539 _G.interruptvector = 0; /* sanity check */
3541 // pic16_pBlockConvert2ISR(pb);
3544 /* if debug then send end of function */
3545 /* if (options.debug && currFunc) */
3547 debugFile->writeEndFunction (currFunc, ic, 1);
3550 pic16_emitpcodeNULLop(POC_RETFIE);
3552 if (IFFUNC_ISCRITICAL(sym->type))
3553 pic16_emitcode("setb","ea");
3556 // pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3558 /* if any registers used */
3559 if (sym->regsUsed) {
3561 /* save the registers used */
3562 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3563 for ( i = sym->regsUsed->size; i >= 0; i--) {
3564 if (bitVectBitValue(sym->regsUsed,i)) {
3566 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3567 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3568 // pic16_regWithIdx(i)->name);
3570 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3572 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3573 // &pic16_pc_preinc1,
3574 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3581 pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3582 /* if debug then send end of function */
3584 debugFile->writeEndFunction (currFunc, ic, 1);
3587 /* insert code to restore stack frame, if user enabled it
3588 * and function is not main() */
3591 if(strcmp(sym->name, "main")) {
3592 if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3593 /* restore stack frame */
3594 if(STACK_MODEL_LARGE)
3595 pic16_emitpcode(POC_MOVFF,
3596 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3597 pic16_emitpcode(POC_MOVFF,
3598 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3602 pic16_emitcode ("return","");
3603 pic16_emitpcodeNULLop(POC_RETURN);
3605 /* Mark the end of a function */
3606 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3612 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3616 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3618 if(dest->type != PO_WREG)
3619 pic16_emitpcode(POC_MOVWF, dest);
3621 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3622 pic16_popGet(AOP(op), offset), dest));
3626 /*-----------------------------------------------------------------*/
3627 /* genRet - generate code for return statement */
3628 /*-----------------------------------------------------------------*/
3629 static void genRet (iCode *ic)
3634 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3635 /* if we have no return value then
3636 * just generate the "ret" */
3641 /* we have something to return then
3642 * move the return value into place */
3643 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3644 size = AOP_SIZE(IC_LEFT(ic));
3648 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3649 // pic16_emitpcode(POC_MOVFF,
3650 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3653 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3654 // pic16_emitpcode(POC_MOVFF,
3655 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3658 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3659 // pic16_emitpcode(POC_MOVFF,
3660 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3663 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3665 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3666 // pic16_emitpcode(POC_MOVFF,
3667 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3670 /* >32-bits, setup stack and FSR0 */
3672 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3673 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3675 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3677 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3682 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3683 pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3685 if(STACK_MODEL_LARGE) {
3686 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3687 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3689 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3694 /* old code, left here for reference -- VR */
3698 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3700 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3701 pic16_emitpcomment("push %s",l);
3704 DEBUGpic16_emitcode(";", "%d", __LINE__);
3705 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3706 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3708 if (strcmp(fReturn[offset],l)) {
3709 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3710 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3711 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3713 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3717 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3727 if (strcmp(fReturn[pushed],"a"))
3728 pic16_emitcode("pop",fReturn[pushed]);
3730 pic16_emitcode("pop","acc");
3736 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3739 /* generate a jump to the return label
3740 * if the next is not the return statement */
3741 if (!(ic->next && ic->next->op == LABEL
3742 && IC_LABEL(ic->next) == returnLabel)) {
3744 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3745 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3749 /*-----------------------------------------------------------------*/
3750 /* genLabel - generates a label */
3751 /*-----------------------------------------------------------------*/
3752 static void genLabel (iCode *ic)
3756 /* special case never generate */
3757 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3758 if (IC_LABEL(ic) == entryLabel)
3761 pic16_emitpLabel(IC_LABEL(ic)->key);
3762 pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3765 /*-----------------------------------------------------------------*/
3766 /* genGoto - generates a goto */
3767 /*-----------------------------------------------------------------*/
3769 static void genGoto (iCode *ic)
3771 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3772 pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3776 /*-----------------------------------------------------------------*/
3777 /* genMultbits :- multiplication of bits */
3778 /*-----------------------------------------------------------------*/
3779 static void genMultbits (operand *left,
3783 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3785 if(!pic16_sameRegs(AOP(result),AOP(right)))
3786 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3788 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3789 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3790 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3795 /*-----------------------------------------------------------------*/
3796 /* genMultOneByte : 8 bit multiplication & division */
3797 /*-----------------------------------------------------------------*/
3798 static void genMultOneByte (operand *left,
3803 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3804 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3805 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3807 /* (if two literals, the value is computed before) */
3808 /* if one literal, literal on the right */
3809 if (AOP_TYPE(left) == AOP_LIT){
3815 /* size is already checked in genMult == 1 */
3816 // size = AOP_SIZE(result);
3818 if (AOP_TYPE(right) == AOP_LIT){
3819 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3820 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3821 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3822 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3824 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3825 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3826 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3827 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3830 pic16_genMult8X8_8 (left, right,result);
3833 /*-----------------------------------------------------------------*/
3834 /* genMultOneWord : 16 bit multiplication */
3835 /*-----------------------------------------------------------------*/
3836 static void genMultOneWord (operand *left,
3841 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3842 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3843 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3845 /* (if two literals, the value is computed before)
3846 * if one literal, literal on the right */
3847 if (AOP_TYPE(left) == AOP_LIT){
3853 /* size is checked already == 2 */
3854 // size = AOP_SIZE(result);
3856 if (AOP_TYPE(right) == AOP_LIT) {
3857 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3858 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3859 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3860 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3862 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3863 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3864 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3865 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3868 pic16_genMult16X16_16(left, right,result);
3871 /*-----------------------------------------------------------------*/
3872 /* genMultOneLong : 32 bit multiplication */
3873 /*-----------------------------------------------------------------*/
3874 static void genMultOneLong (operand *left,
3879 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3880 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3881 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3883 /* (if two literals, the value is computed before)
3884 * if one literal, literal on the right */
3885 if (AOP_TYPE(left) == AOP_LIT){
3891 /* size is checked already == 4 */
3892 // size = AOP_SIZE(result);
3894 if (AOP_TYPE(right) == AOP_LIT) {
3895 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3896 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3897 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3898 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3900 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3901 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3902 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3903 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3906 pic16_genMult32X32_32(left, right,result);
3911 /*-----------------------------------------------------------------*/
3912 /* genMult - generates code for multiplication */
3913 /*-----------------------------------------------------------------*/
3914 static void genMult (iCode *ic)
3916 operand *left = IC_LEFT(ic);
3917 operand *right = IC_RIGHT(ic);
3918 operand *result= IC_RESULT(ic);
3920 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3921 /* assign the amsops */
3922 pic16_aopOp (left,ic,FALSE);
3923 pic16_aopOp (right,ic,FALSE);
3924 pic16_aopOp (result,ic,TRUE);
3926 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3928 /* special cases first *
3930 if (AOP_TYPE(left) == AOP_CRY
3931 && AOP_TYPE(right)== AOP_CRY) {
3932 genMultbits(left,right,result);
3936 /* if both are of size == 1 */
3937 if(AOP_SIZE(left) == 1
3938 && AOP_SIZE(right) == 1) {
3939 genMultOneByte(left,right,result);
3943 /* if both are of size == 2 */
3944 if(AOP_SIZE(left) == 2
3945 && AOP_SIZE(right) == 2) {
3946 genMultOneWord(left, right, result);
3950 /* if both are of size == 4 */
3951 if(AOP_SIZE(left) == 4
3952 && AOP_SIZE(right) == 4) {
3953 genMultOneLong(left, right, result);
3957 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3960 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3961 /* should have been converted to function call */
3965 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3966 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3967 pic16_freeAsmop(result,NULL,ic,TRUE);
3970 /*-----------------------------------------------------------------*/
3971 /* genDivbits :- division of bits */
3972 /*-----------------------------------------------------------------*/
3973 static void genDivbits (operand *left,
3980 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3981 /* the result must be bit */
3982 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3983 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3987 pic16_emitcode("div","ab");
3988 pic16_emitcode("rrc","a");
3989 pic16_aopPut(AOP(result),"c",0);
3992 /*-----------------------------------------------------------------*/
3993 /* genDivOneByte : 8 bit division */
3994 /*-----------------------------------------------------------------*/
3995 static void genDivOneByte (operand *left,
3999 sym_link *opetype = operandType(result);
4004 /* result = divident / divisor
4005 * - divident may be a register or a literal,
4006 * - divisor may be a register or a literal,
4007 * so there are 3 cases (literal / literal is optimized
4008 * by the front-end) to handle.
4009 * In addition we must handle signed and unsigned, which
4010 * result in 6 final different cases -- VR */
4012 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4013 size = AOP_SIZE(result) - 1;
4015 /* signed or unsigned */
4016 if (SPEC_USIGN(opetype)) {
4017 pCodeOp *pct1, /* count */
4020 symbol *label1, *label2, *label3;;
4023 /* unsigned is easy */
4025 pct1 = pic16_popGetTempReg();
4026 pct2 = pic16_popGetTempReg();
4027 pct3 = pic16_popGetTempReg();
4029 label1 = newiTempLabel(NULL);
4030 label2 = newiTempLabel(NULL);
4031 label3 = newiTempLabel(NULL);
4033 /* the following algorithm is extracted from divuint.c */
4035 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4036 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4038 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4040 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4042 pic16_emitpLabel(label1->key);
4045 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4049 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4053 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4055 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4056 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4058 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4059 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4060 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4062 pic16_emitpLabel( label3->key );
4063 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4064 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4068 pic16_emitpLabel(label2->key);
4069 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4070 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4071 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4073 /* result is in wreg */
4074 if(AOP_TYPE(result) != AOP_ACC)
4075 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4077 pic16_popReleaseTempReg( pct3 );
4078 pic16_popReleaseTempReg( pct2 );
4079 pic16_popReleaseTempReg( pct1 );
4084 /* signed is a little bit more difficult */
4086 /* save the signs of the operands */
4087 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4089 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4090 pic16_emitcode("push","acc"); /* save it on the stack */
4092 /* now sign adjust for both left & right */
4093 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4095 lbl = newiTempLabel(NULL);
4096 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4097 pic16_emitcode("cpl","a");
4098 pic16_emitcode("inc","a");
4099 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4100 pic16_emitcode("mov","b,a");
4102 /* sign adjust left side */
4103 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4106 lbl = newiTempLabel(NULL);
4107 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4108 pic16_emitcode("cpl","a");
4109 pic16_emitcode("inc","a");
4110 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4112 /* now the division */
4113 pic16_emitcode("div","ab");
4114 /* we are interested in the lower order
4116 pic16_emitcode("mov","b,a");
4117 lbl = newiTempLabel(NULL);
4118 pic16_emitcode("pop","acc");
4119 /* if there was an over flow we don't
4120 adjust the sign of the result */
4121 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4122 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4124 pic16_emitcode("clr","a");
4125 pic16_emitcode("subb","a,b");
4126 pic16_emitcode("mov","b,a");
4127 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4129 /* now we are done */
4130 pic16_aopPut(AOP(result),"b",0);
4132 pic16_emitcode("mov","c,b.7");
4133 pic16_emitcode("subb","a,acc");
4136 pic16_aopPut(AOP(result),"a",offset++);
4140 /*-----------------------------------------------------------------*/
4141 /* genDiv - generates code for division */
4142 /*-----------------------------------------------------------------*/
4143 static void genDiv (iCode *ic)
4145 operand *left = IC_LEFT(ic);
4146 operand *right = IC_RIGHT(ic);
4147 operand *result= IC_RESULT(ic);
4150 /* Division is a very lengthy algorithm, so it is better
4151 * to call support routines than inlining algorithm.
4152 * Division functions written here just in case someone
4153 * wants to inline and not use the support libraries -- VR */
4155 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4156 /* assign the amsops */
4157 pic16_aopOp (left,ic,FALSE);
4158 pic16_aopOp (right,ic,FALSE);
4159 pic16_aopOp (result,ic,TRUE);
4161 /* special cases first */
4163 if (AOP_TYPE(left) == AOP_CRY &&
4164 AOP_TYPE(right)== AOP_CRY) {
4165 genDivbits(left,right,result);
4169 /* if both are of size == 1 */
4170 if (AOP_SIZE(left) == 1 &&
4171 AOP_SIZE(right) == 1 ) {
4172 genDivOneByte(left,right,result);
4176 /* should have been converted to function call */
4179 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4180 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4181 pic16_freeAsmop(result,NULL,ic,TRUE);
4184 /*-----------------------------------------------------------------*/
4185 /* genModbits :- modulus of bits */
4186 /*-----------------------------------------------------------------*/
4187 static void genModbits (operand *left,
4194 /* the result must be bit */
4195 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4196 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4200 pic16_emitcode("div","ab");
4201 pic16_emitcode("mov","a,b");
4202 pic16_emitcode("rrc","a");
4203 pic16_aopPut(AOP(result),"c",0);
4206 /*-----------------------------------------------------------------*/
4207 /* genModOneByte : 8 bit modulus */
4208 /*-----------------------------------------------------------------*/
4209 static void genModOneByte (operand *left,
4213 sym_link *opetype = operandType(result);
4217 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4218 /* signed or unsigned */
4219 if (SPEC_USIGN(opetype)) {
4220 /* unsigned is easy */
4221 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4222 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4224 pic16_emitcode("div","ab");
4225 pic16_aopPut(AOP(result),"b",0);
4229 /* signed is a little bit more difficult */
4231 /* save the signs of the operands */
4232 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4235 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4236 pic16_emitcode("push","acc"); /* save it on the stack */
4238 /* now sign adjust for both left & right */
4239 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4242 lbl = newiTempLabel(NULL);
4243 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4244 pic16_emitcode("cpl","a");
4245 pic16_emitcode("inc","a");
4246 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4247 pic16_emitcode("mov","b,a");
4249 /* sign adjust left side */
4250 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4253 lbl = newiTempLabel(NULL);
4254 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4255 pic16_emitcode("cpl","a");
4256 pic16_emitcode("inc","a");
4257 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4259 /* now the multiplication */
4260 pic16_emitcode("div","ab");
4261 /* we are interested in the lower order
4263 lbl = newiTempLabel(NULL);
4264 pic16_emitcode("pop","acc");
4265 /* if there was an over flow we don't
4266 adjust the sign of the result */
4267 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4268 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4270 pic16_emitcode("clr","a");
4271 pic16_emitcode("subb","a,b");
4272 pic16_emitcode("mov","b,a");
4273 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4275 /* now we are done */
4276 pic16_aopPut(AOP(result),"b",0);
4280 /*-----------------------------------------------------------------*/
4281 /* genMod - generates code for division */
4282 /*-----------------------------------------------------------------*/
4283 static void genMod (iCode *ic)
4285 operand *left = IC_LEFT(ic);
4286 operand *right = IC_RIGHT(ic);
4287 operand *result= IC_RESULT(ic);
4289 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4290 /* assign the amsops */
4291 pic16_aopOp (left,ic,FALSE);
4292 pic16_aopOp (right,ic,FALSE);
4293 pic16_aopOp (result,ic,TRUE);
4295 /* special cases first */
4297 if (AOP_TYPE(left) == AOP_CRY &&
4298 AOP_TYPE(right)== AOP_CRY) {
4299 genModbits(left,right,result);
4303 /* if both are of size == 1 */
4304 if (AOP_SIZE(left) == 1 &&
4305 AOP_SIZE(right) == 1 ) {
4306 genModOneByte(left,right,result);
4310 /* should have been converted to function call */
4314 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4315 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4316 pic16_freeAsmop(result,NULL,ic,TRUE);
4319 /*-----------------------------------------------------------------*/
4320 /* genIfxJump :- will create a jump depending on the ifx */
4321 /*-----------------------------------------------------------------*/
4323 note: May need to add parameter to indicate when a variable is in bit space.
4325 static void genIfxJump (iCode *ic, char *jval)
4328 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4329 /* if true label then we jump if condition
4331 if ( IC_TRUE(ic) ) {
4333 if(strcmp(jval,"a") == 0)
4335 else if (strcmp(jval,"c") == 0)
4338 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4339 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1));
4342 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4343 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4347 /* false label is present */
4348 if(strcmp(jval,"a") == 0)
4350 else if (strcmp(jval,"c") == 0)
4353 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4354 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1));
4357 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4358 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4363 /* mark the icode as generated */
4370 /*-----------------------------------------------------------------*/
4372 /*-----------------------------------------------------------------*/
4373 static void genSkip(iCode *ifx,int status_bit)
4375 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4379 if ( IC_TRUE(ifx) ) {
4380 switch(status_bit) {
4395 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4396 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4400 switch(status_bit) {
4414 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4415 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4422 /*-----------------------------------------------------------------*/
4424 /*-----------------------------------------------------------------*/
4425 static void genSkipc(resolvedIfx *rifx)
4427 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4437 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4438 rifx->generated = 1;
4441 /*-----------------------------------------------------------------*/
4443 /*-----------------------------------------------------------------*/
4444 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4446 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4451 if( (rifx->condition ^ invert_condition) & 1)
4456 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4457 rifx->generated = 1;
4461 /*-----------------------------------------------------------------*/
4463 /*-----------------------------------------------------------------*/
4464 static void genSkipz(iCode *ifx, int condition)
4475 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4477 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4480 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4482 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4487 /*-----------------------------------------------------------------*/
4489 /*-----------------------------------------------------------------*/
4490 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4496 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4498 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4501 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4502 rifx->generated = 1;
4506 /*-----------------------------------------------------------------*/
4507 /* genChkZeroes :- greater or less than comparison */
4508 /* For each byte in a literal that is zero, inclusive or the */
4509 /* the corresponding byte in the operand with W */
4510 /* returns true if any of the bytes are zero */
4511 /*-----------------------------------------------------------------*/
4512 static int genChkZeroes(operand *op, int lit, int size)
4519 i = (lit >> (size*8)) & 0xff;
4523 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4525 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4534 /*-----------------------------------------------------------------*/
4535 /* genCmp :- greater or less than comparison */
4536 /*-----------------------------------------------------------------*/
4537 static void genCmp (operand *left,operand *right,
4538 operand *result, iCode *ifx, int sign)
4540 int size; //, offset = 0 ;
4541 unsigned long lit = 0L,i = 0;
4542 resolvedIfx rFalseIfx;
4543 // resolvedIfx rTrueIfx;
4545 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4548 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4549 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4553 resolveIfx(&rFalseIfx,ifx);
4554 truelbl = newiTempLabel(NULL);
4555 size = max(AOP_SIZE(left),AOP_SIZE(right));
4557 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4561 /* if literal is on the right then swap with left */
4562 if ((AOP_TYPE(right) == AOP_LIT)) {
4563 operand *tmp = right ;
4564 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4565 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4568 lit = (lit - 1) & mask;
4571 rFalseIfx.condition ^= 1;
4574 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4575 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4579 //if(IC_TRUE(ifx) == NULL)
4580 /* if left & right are bit variables */
4581 if (AOP_TYPE(left) == AOP_CRY &&
4582 AOP_TYPE(right) == AOP_CRY ) {
4583 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4584 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4586 /* subtract right from left if at the
4587 end the carry flag is set then we know that
4588 left is greater than right */
4590 symbol *lbl = newiTempLabel(NULL);
4593 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4594 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+labelOffset, lbl->key+100+labelOffset);
4598 if(AOP_TYPE(right) == AOP_LIT) {
4600 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4602 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4609 genSkipCond(&rFalseIfx,left,size-1,7);
4611 /* no need to compare to 0...*/
4612 /* NOTE: this is a de-generate compare that most certainly
4613 * creates some dead code. */
4614 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4616 if(ifx) ifx->generated = 1;
4623 //i = (lit >> (size*8)) & 0xff;
4624 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4626 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4628 i = ((0-lit) & 0xff);
4631 /* lit is 0x7f, all signed chars are less than
4632 * this except for 0x7f itself */
4633 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4634 genSkipz2(&rFalseIfx,0);
4636 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4637 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4638 genSkipc(&rFalseIfx);
4643 genSkipz2(&rFalseIfx,1);
4645 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4646 genSkipc(&rFalseIfx);
4650 if(ifx) ifx->generated = 1;
4654 /* chars are out of the way. now do ints and longs */
4657 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4664 genSkipCond(&rFalseIfx,left,size,7);
4665 if(ifx) ifx->generated = 1;
4670 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4672 //rFalseIfx.condition ^= 1;
4673 //genSkipCond(&rFalseIfx,left,size,7);
4674 //rFalseIfx.condition ^= 1;
4676 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4677 if(rFalseIfx.condition)
4678 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4680 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4682 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4683 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4684 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4687 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4689 if(rFalseIfx.condition) {
4691 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4697 genSkipc(&rFalseIfx);
4698 pic16_emitpLabel(truelbl->key);
4699 if(ifx) ifx->generated = 1;
4706 if( (lit & 0xff) == 0) {
4707 /* lower byte is zero */
4708 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4709 i = ((lit >> 8) & 0xff) ^0x80;
4710 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4711 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4712 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4713 genSkipc(&rFalseIfx);
4716 if(ifx) ifx->generated = 1;
4721 /* Special cases for signed longs */
4722 if( (lit & 0xffffff) == 0) {
4723 /* lower byte is zero */
4724 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4725 i = ((lit >> 8*3) & 0xff) ^0x80;
4726 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4727 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4728 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4729 genSkipc(&rFalseIfx);
4732 if(ifx) ifx->generated = 1;
4740 if(lit & (0x80 << (size*8))) {
4741 /* lit is negative */
4742 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4744 //genSkipCond(&rFalseIfx,left,size,7);
4746 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4748 if(rFalseIfx.condition)
4749 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4751 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4755 /* lit is positive */
4756 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4757 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4758 if(rFalseIfx.condition)
4759 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4761 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4766 This works, but is only good for ints.
4767 It also requires a "known zero" register.
4768 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4769 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4770 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
4771 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4772 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4773 genSkipc(&rFalseIfx);
4775 pic16_emitpLabel(truelbl->key);
4776 if(ifx) ifx->generated = 1;
4780 /* There are no more special cases, so perform a general compare */
4782 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4783 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4787 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4789 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4791 //rFalseIfx.condition ^= 1;
4792 genSkipc(&rFalseIfx);
4794 pic16_emitpLabel(truelbl->key);
4796 if(ifx) ifx->generated = 1;
4803 /* sign is out of the way. So now do an unsigned compare */
4804 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4807 /* General case - compare to an unsigned literal on the right.*/
4809 i = (lit >> (size*8)) & 0xff;
4810 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4811 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4813 i = (lit >> (size*8)) & 0xff;
4816 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4818 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4820 /* this byte of the lit is zero,
4821 *if it's not the last then OR in the variable */
4823 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4828 pic16_emitpLabel(lbl->key);
4829 // pic16_emitpLabel(truelbl->key);
4830 //if(emitFinalCheck)
4831 genSkipc(&rFalseIfx);
4833 pic16_emitpLabel(truelbl->key);
4835 if(ifx) ifx->generated = 1;
4842 if(AOP_TYPE(left) == AOP_LIT) {
4843 //symbol *lbl = newiTempLabel(NULL);
4845 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4848 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4851 if((lit == 0) && (sign == 0)){
4854 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4856 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4858 genSkipz2(&rFalseIfx,0);
4859 if(ifx) ifx->generated = 1;
4866 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4867 /* degenerate compare can never be true */
4868 if(rFalseIfx.condition == 0)
4869 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4871 if(ifx) ifx->generated = 1;
4876 /* signed comparisons to a literal byte */
4878 int lp1 = (lit+1) & 0xff;
4880 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4883 rFalseIfx.condition ^= 1;
4884 genSkipCond(&rFalseIfx,right,0,7);
4887 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4888 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4889 genSkipz2(&rFalseIfx,1);
4892 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4893 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4894 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4895 rFalseIfx.condition ^= 1;
4896 genSkipc(&rFalseIfx);
4900 /* unsigned comparisons to a literal byte */
4902 switch(lit & 0xff ) {
4904 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4905 genSkipz2(&rFalseIfx,0);
4908 rFalseIfx.condition ^= 1;
4909 genSkipCond(&rFalseIfx,right,0,7);
4913 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4914 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4915 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4916 rFalseIfx.condition ^= 1;
4917 if (AOP_TYPE(result) == AOP_CRY)
4918 genSkipc(&rFalseIfx);
4920 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4921 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4927 if(ifx) ifx->generated = 1;
4928 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
4934 /* Size is greater than 1 */
4942 /* this means lit = 0xffffffff, or -1 */
4945 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4946 rFalseIfx.condition ^= 1;
4947 genSkipCond(&rFalseIfx,right,size,7);
4948 if(ifx) ifx->generated = 1;
4955 if(rFalseIfx.condition) {
4956 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4957 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4960 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4962 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4966 if(rFalseIfx.condition) {
4967 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4968 pic16_emitpLabel(truelbl->key);
4970 rFalseIfx.condition ^= 1;
4971 genSkipCond(&rFalseIfx,right,s,7);
4974 if(ifx) ifx->generated = 1;
4978 if((size == 1) && (0 == (lp1&0xff))) {
4979 /* lower byte of signed word is zero */
4980 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4981 i = ((lp1 >> 8) & 0xff) ^0x80;
4982 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4983 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4984 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4985 rFalseIfx.condition ^= 1;
4986 genSkipc(&rFalseIfx);
4989 if(ifx) ifx->generated = 1;
4993 if(lit & (0x80 << (size*8))) {
4994 /* Lit is less than zero */
4995 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
4996 //rFalseIfx.condition ^= 1;
4997 //genSkipCond(&rFalseIfx,left,size,7);
4998 //rFalseIfx.condition ^= 1;
4999 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5000 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5002 if(rFalseIfx.condition)
5003 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5005 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5009 /* Lit is greater than or equal to zero */
5010 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5011 //rFalseIfx.condition ^= 1;
5012 //genSkipCond(&rFalseIfx,right,size,7);
5013 //rFalseIfx.condition ^= 1;
5015 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5016 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5018 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5019 if(rFalseIfx.condition)
5020 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5022 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5027 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5028 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5032 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5034 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5036 rFalseIfx.condition ^= 1;
5037 //rFalseIfx.condition = 1;
5038 genSkipc(&rFalseIfx);
5040 pic16_emitpLabel(truelbl->key);
5042 if(ifx) ifx->generated = 1;
5047 /* compare word or long to an unsigned literal on the right.*/
5052 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5055 break; /* handled above */
5058 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5060 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5061 genSkipz2(&rFalseIfx,0);
5065 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5067 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5070 if(rFalseIfx.condition)
5071 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5073 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5076 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5077 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5079 rFalseIfx.condition ^= 1;
5080 genSkipc(&rFalseIfx);
5083 pic16_emitpLabel(truelbl->key);
5085 if(ifx) ifx->generated = 1;
5091 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5092 i = (lit >> (size*8)) & 0xff;
5094 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5095 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5098 i = (lit >> (size*8)) & 0xff;
5101 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5103 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5105 /* this byte of the lit is zero,
5106 * if it's not the last then OR in the variable */
5108 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5113 pic16_emitpLabel(lbl->key);
5115 rFalseIfx.condition ^= 1;
5117 genSkipc(&rFalseIfx);
5121 pic16_emitpLabel(truelbl->key);
5122 if(ifx) ifx->generated = 1;
5126 /* Compare two variables */
5128 DEBUGpic16_emitcode(";sign","%d",sign);
5132 /* Sigh. thus sucks... */
5134 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5135 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5136 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5137 pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5138 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5139 pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5141 /* Signed char comparison */
5142 /* Special thanks to Nikolai Golovchenko for this snippet */
5143 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5144 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5145 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5146 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5147 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5148 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5150 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5151 genSkipc(&rFalseIfx);
5153 if(ifx) ifx->generated = 1;
5159 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5160 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5164 /* The rest of the bytes of a multi-byte compare */
5168 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5171 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5172 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5177 pic16_emitpLabel(lbl->key);
5179 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5180 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5181 (AOP_TYPE(result) == AOP_REG)) {
5182 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5183 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5185 genSkipc(&rFalseIfx);
5187 //genSkipc(&rFalseIfx);
5188 if(ifx) ifx->generated = 1;
5195 if ((AOP_TYPE(result) != AOP_CRY)
5196 && AOP_SIZE(result)) {
5197 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5198 // pic16_emitpLabel( rFalseIfx.lbl->key );
5200 pic16_outBitC(result);
5202 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5203 /* if the result is used in the next
5204 ifx conditional branch then generate
5205 code a little differently */
5207 genIfxJump (ifx,"c");
5209 pic16_outBitC(result);
5210 /* leave the result in acc */
5215 /*-----------------------------------------------------------------*/
5216 /* genCmpGt :- greater than comparison */
5217 /*-----------------------------------------------------------------*/
5218 static void genCmpGt (iCode *ic, iCode *ifx)
5220 operand *left, *right, *result;
5221 sym_link *letype , *retype;
5224 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5226 right= IC_RIGHT(ic);
5227 result = IC_RESULT(ic);
5229 letype = getSpec(operandType(left));
5230 retype =getSpec(operandType(right));
5231 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5232 /* assign the amsops */
5233 pic16_aopOp (left,ic,FALSE);
5234 pic16_aopOp (right,ic,FALSE);
5235 pic16_aopOp (result,ic,TRUE);
5237 genCmp(right, left, result, ifx, sign);
5239 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5240 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5241 pic16_freeAsmop(result,NULL,ic,TRUE);
5244 /*-----------------------------------------------------------------*/
5245 /* genCmpLt - less than comparisons */
5246 /*-----------------------------------------------------------------*/
5247 static void genCmpLt (iCode *ic, iCode *ifx)
5249 operand *left, *right, *result;
5250 sym_link *letype , *retype;
5253 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5255 right= IC_RIGHT(ic);
5256 result = IC_RESULT(ic);
5258 letype = getSpec(operandType(left));
5259 retype =getSpec(operandType(right));
5260 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5262 /* assign the amsops */
5263 pic16_aopOp (left,ic,FALSE);
5264 pic16_aopOp (right,ic,FALSE);
5265 pic16_aopOp (result,ic,TRUE);
5267 genCmp(left, right, result, ifx, sign);
5269 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5270 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5271 pic16_freeAsmop(result,NULL,ic,TRUE);
5276 // FIXME reenable literal optimisation when the pic16 port is stable
5278 /*-----------------------------------------------------------------*/
5279 /* genc16bit2lit - compare a 16 bit value to a literal */
5280 /*-----------------------------------------------------------------*/
5281 static void genc16bit2lit(operand *op, int lit, int offset)
5285 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
5286 if( (lit&0xff) == 0)
5291 switch( BYTEofLONG(lit,i)) {
5293 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5296 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5299 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5302 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5303 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5308 switch( BYTEofLONG(lit,i)) {
5310 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5314 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5318 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5321 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5323 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5332 /*-----------------------------------------------------------------*/
5333 /* gencjneshort - compare and jump if not equal */
5334 /*-----------------------------------------------------------------*/
5335 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5337 int size = max(AOP_SIZE(left),AOP_SIZE(right));
5339 int res_offset = 0; /* the result may be a different size then left or right */
5340 int res_size = AOP_SIZE(result);
5342 symbol *lbl, *lbl_done;
5344 unsigned long lit = 0L;
5345 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5347 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5348 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5350 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
5351 resolveIfx(&rIfx,ifx);
5352 lbl = newiTempLabel(NULL);
5353 lbl_done = newiTempLabel(NULL);
5356 /* if the left side is a literal or
5357 if the right is in a pointer register and left
5359 if ((AOP_TYPE(left) == AOP_LIT) ||
5360 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5365 if(AOP_TYPE(right) == AOP_LIT)
5366 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5368 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5369 preserve_result = 1;
5371 if(result && !preserve_result)
5374 for(i = 0; i < AOP_SIZE(result); i++)
5375 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5379 /* if the right side is a literal then anything goes */
5380 if (AOP_TYPE(right) == AOP_LIT &&
5381 AOP_TYPE(left) != AOP_DIR ) {
5384 genc16bit2lit(left, lit, 0);
5386 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5389 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5392 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5393 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5395 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5399 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5401 if(res_offset < res_size-1)
5409 /* if the right side is in a register or in direct space or
5410 if the left is a pointer register & right is not */
5411 else if (AOP_TYPE(right) == AOP_REG ||
5412 AOP_TYPE(right) == AOP_DIR ||
5413 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5414 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5415 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5416 int lbl_key = lbl->key;
5419 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5420 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5422 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5423 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5424 __FUNCTION__,__LINE__);
5428 /* switch(size) { */
5430 /* genc16bit2lit(left, lit, 0); */
5432 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5437 if((AOP_TYPE(left) == AOP_DIR) &&
5438 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5440 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5441 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5443 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5445 switch (lit & 0xff) {
5447 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5450 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5451 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5452 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5456 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5457 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5458 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5459 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5463 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5464 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5469 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5472 if(AOP_TYPE(result) == AOP_CRY) {
5473 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5478 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5480 /* fix me. probably need to check result size too */
5481 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5486 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5487 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5494 if(res_offset < res_size-1)
5499 } else if(AOP_TYPE(right) == AOP_REG &&
5500 AOP_TYPE(left) != AOP_DIR){
5503 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5504 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5505 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5510 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5512 if(res_offset < res_size-1)
5517 /* right is a pointer reg need both a & b */
5519 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5521 pic16_emitcode("mov","b,%s",l);
5522 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5523 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5528 if(result && preserve_result)
5531 for(i = 0; i < AOP_SIZE(result); i++)
5532 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5535 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5537 if(result && preserve_result)
5538 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5541 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5543 pic16_emitpLabel(lbl->key);
5545 if(result && preserve_result)
5548 for(i = 0; i < AOP_SIZE(result); i++)
5549 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5551 pic16_emitpLabel(lbl_done->key);
5554 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5562 /*-----------------------------------------------------------------*/
5563 /* gencjne - compare and jump if not equal */
5564 /*-----------------------------------------------------------------*/
5565 static void gencjne(operand *left, operand *right, iCode *ifx)
5567 symbol *tlbl = newiTempLabel(NULL);
5569 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5570 gencjneshort(left, right, lbl);
5572 pic16_emitcode("mov","a,%s",one);
5573 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5574 pic16_emitcode("","%05d_DS_:",lbl->key+100);
5575 pic16_emitcode("clr","a");
5576 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5578 pic16_emitpLabel(lbl->key);
5579 pic16_emitpLabel(tlbl->key);
5585 /*-----------------------------------------------------------------*/
5586 /* is_LitOp - check if operand has to be treated as literal */
5587 /*-----------------------------------------------------------------*/
5588 static bool is_LitOp(operand *op)
5590 return (AOP_TYPE(op) == AOP_LIT)
5591 || ( (AOP_TYPE(op) == AOP_PCODE)
5592 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5593 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));
5596 /*-----------------------------------------------------------------*/
5597 /* is_LitAOp - check if operand has to be treated as literal */
5598 /*-----------------------------------------------------------------*/
5599 static bool is_LitAOp(asmop *aop)
5601 return (aop->type == AOP_LIT)
5602 || ( (aop->type == AOP_PCODE)
5603 && ( (aop->aopu.pcop->type == PO_LITERAL)
5604 || (aop->aopu.pcop->type == PO_IMMEDIATE) ));
5609 /*-----------------------------------------------------------------*/
5610 /* genCmpEq - generates code for equal to */
5611 /*-----------------------------------------------------------------*/
5612 static void genCmpEq (iCode *ic, iCode *ifx)
5614 operand *left, *right, *result;
5615 symbol *falselbl = newiTempLabel(NULL);
5616 symbol *donelbl = newiTempLabel(NULL);
5618 int preserve_result = 0;
5619 int generate_result = 0;
5622 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5623 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5624 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5626 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5627 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5629 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5631 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5632 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5636 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5638 operand *tmp = right ;
5643 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5644 preserve_result = 1;
5646 if(result && AOP_SIZE(result))
5647 generate_result = 1;
5649 if(generate_result && !preserve_result)
5651 for(i = 0; i < AOP_SIZE(result); i++)
5652 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5655 for(i=0; i < AOP_SIZE(left); i++)
5657 if(AOP_TYPE(left) != AOP_ACC)
5660 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5662 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5665 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
5667 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
5669 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5674 if(generate_result && preserve_result)
5676 for(i = 0; i < AOP_SIZE(result); i++)
5677 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5681 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5683 if(generate_result && preserve_result)
5684 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5686 if(ifx && IC_TRUE(ifx))
5687 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5689 if(ifx && IC_FALSE(ifx))
5690 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5692 pic16_emitpLabel(falselbl->key);
5696 if(ifx && IC_FALSE(ifx))
5697 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5699 if(generate_result && preserve_result)
5701 for(i = 0; i < AOP_SIZE(result); i++)
5702 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5705 pic16_emitpLabel(donelbl->key);
5711 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5712 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5713 pic16_freeAsmop(result,NULL,ic,TRUE);
5719 // old version kept for reference
5721 /*-----------------------------------------------------------------*/
5722 /* genCmpEq - generates code for equal to */
5723 /*-----------------------------------------------------------------*/
5724 static void genCmpEq (iCode *ic, iCode *ifx)
5726 operand *left, *right, *result;
5727 unsigned long lit = 0L;
5729 symbol *falselbl = newiTempLabel(NULL);
5732 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5735 DEBUGpic16_emitcode ("; ifx is non-null","");
5737 DEBUGpic16_emitcode ("; ifx is null","");
5739 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5740 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5741 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5743 size = max(AOP_SIZE(left),AOP_SIZE(right));
5745 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5747 /* if literal, literal on the right or
5748 if the right is in a pointer register and left
5750 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
5751 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5752 operand *tmp = right ;
5758 if(ifx && !AOP_SIZE(result)){
5760 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
5761 /* if they are both bit variables */
5762 if (AOP_TYPE(left) == AOP_CRY &&
5763 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5764 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
5765 if(AOP_TYPE(right) == AOP_LIT){
5766 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5768 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5769 pic16_emitcode("cpl","c");
5770 } else if(lit == 1L) {
5771 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5773 pic16_emitcode("clr","c");
5775 /* AOP_TYPE(right) == AOP_CRY */
5777 symbol *lbl = newiTempLabel(NULL);
5778 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5779 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5780 pic16_emitcode("cpl","c");
5781 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5783 /* if true label then we jump if condition
5785 tlbl = newiTempLabel(NULL);
5786 if ( IC_TRUE(ifx) ) {
5787 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5788 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5790 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5791 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5793 pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5796 /* left and right are both bit variables, result is carry */
5799 resolveIfx(&rIfx,ifx);
5801 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5802 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5803 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5804 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5809 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
5811 /* They're not both bit variables. Is the right a literal? */
5812 if(AOP_TYPE(right) == AOP_LIT) {
5813 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5818 switch(lit & 0xff) {
5820 if ( IC_TRUE(ifx) ) {
5821 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5823 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5825 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5826 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5830 if ( IC_TRUE(ifx) ) {
5831 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5833 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5835 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5836 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5840 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5842 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5847 /* end of size == 1 */
5851 genc16bit2lit(left,lit,offset);
5854 /* end of size == 2 */
5859 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5860 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5861 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5862 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5865 /* search for patterns that can be optimized */
5867 genc16bit2lit(left,lit,0);
5871 emitSKPZ; // if hi word unequal
5873 emitSKPNZ; // if hi word equal
5875 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5876 genc16bit2lit(left,lit,2);
5879 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5880 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5884 pic16_emitpLabel(falselbl->key);
5893 } else if(AOP_TYPE(right) == AOP_CRY ) {
5894 /* we know the left is not a bit, but that the right is */
5895 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5896 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5897 pic16_popGet(AOP(right),offset));
5898 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5900 /* if the two are equal, then W will be 0 and the Z bit is set
5901 * we could test Z now, or go ahead and check the high order bytes if
5902 * the variable we're comparing is larger than a byte. */
5905 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5907 if ( IC_TRUE(ifx) ) {
5909 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5910 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5913 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5914 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5918 /* They're both variables that are larger than bits */
5921 tlbl = newiTempLabel(NULL);
5924 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5925 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5927 if ( IC_TRUE(ifx) ) {
5931 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5933 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5934 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5938 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5941 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5942 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5947 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5949 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5950 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5954 if(s>1 && IC_TRUE(ifx)) {
5955 pic16_emitpLabel(tlbl->key);
5956 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
5960 /* mark the icode as generated */
5965 /* if they are both bit variables */
5966 if (AOP_TYPE(left) == AOP_CRY &&
5967 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5968 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
5969 if(AOP_TYPE(right) == AOP_LIT){
5970 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5972 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5973 pic16_emitcode("cpl","c");
5974 } else if(lit == 1L) {
5975 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5977 pic16_emitcode("clr","c");
5979 /* AOP_TYPE(right) == AOP_CRY */
5981 symbol *lbl = newiTempLabel(NULL);
5982 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5983 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5984 pic16_emitcode("cpl","c");
5985 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5988 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5989 pic16_outBitC(result);
5993 genIfxJump (ifx,"c");
5996 /* if the result is used in an arithmetic operation
5997 then put the result in place */
5998 pic16_outBitC(result);
6001 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
6002 gencjne(left,right,result,ifx);
6005 gencjne(left,right,newiTempLabel(NULL));
6007 if(IC_TRUE(ifx)->key)
6008 gencjne(left,right,IC_TRUE(ifx)->key);
6010 gencjne(left,right,IC_FALSE(ifx)->key);
6014 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6015 pic16_aopPut(AOP(result),"a",0);
6020 genIfxJump (ifx,"a");
6024 /* if the result is used in an arithmetic operation
6025 then put the result in place */
6027 if (AOP_TYPE(result) != AOP_CRY)
6028 pic16_outAcc(result);
6030 /* leave the result in acc */
6034 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6035 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6036 pic16_freeAsmop(result,NULL,ic,TRUE);
6040 /*-----------------------------------------------------------------*/
6041 /* ifxForOp - returns the icode containing the ifx for operand */
6042 /*-----------------------------------------------------------------*/
6043 static iCode *ifxForOp ( operand *op, iCode *ic )
6045 /* if true symbol then needs to be assigned */
6046 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6047 if (IS_TRUE_SYMOP(op))
6050 /* if this has register type condition and
6051 the next instruction is ifx with the same operand
6052 and live to of the operand is upto the ifx only then */
6054 && ic->next->op == IFX
6055 && IC_COND(ic->next)->key == op->key
6056 && OP_SYMBOL(op)->liveTo <= ic->next->seq
6058 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6063 ic->next->op == IFX &&
6064 IC_COND(ic->next)->key == op->key) {
6065 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6069 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6071 ic->next->op == IFX)
6072 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6075 ic->next->op == IFX &&
6076 IC_COND(ic->next)->key == op->key) {
6077 DEBUGpic16_emitcode ("; "," key is okay");
6078 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6079 OP_SYMBOL(op)->liveTo,
6084 /* the code below is completely untested
6085 * it just allows ulong2fs.c compile -- VR */
6088 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6089 __FILE__, __FUNCTION__, __LINE__);
6091 /* if this has register type condition and
6092 the next instruction is ifx with the same operand
6093 and live to of the operand is upto the ifx only then */
6095 ic->next->op == IFX &&
6096 IC_COND(ic->next)->key == op->key &&
6097 OP_SYMBOL(op)->liveTo <= ic->next->seq )
6101 ic->next->op == IFX &&
6102 IC_COND(ic->next)->key == op->key) {
6103 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6107 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6108 __FILE__, __FUNCTION__, __LINE__);
6110 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
6115 /*-----------------------------------------------------------------*/
6116 /* genAndOp - for && operation */
6117 /*-----------------------------------------------------------------*/
6118 static void genAndOp (iCode *ic)
6120 operand *left,*right, *result;
6123 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
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 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6128 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6129 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6131 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6133 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6134 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6135 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6137 /* if both are bit variables */
6138 /* if (AOP_TYPE(left) == AOP_CRY && */
6139 /* AOP_TYPE(right) == AOP_CRY ) { */
6140 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6141 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6142 /* pic16_outBitC(result); */
6144 /* tlbl = newiTempLabel(NULL); */
6145 /* pic16_toBoolean(left); */
6146 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6147 /* pic16_toBoolean(right); */
6148 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6149 /* pic16_outBitAcc(result); */
6152 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6153 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6154 pic16_freeAsmop(result,NULL,ic,TRUE);
6158 /*-----------------------------------------------------------------*/
6159 /* genOrOp - for || operation */
6160 /*-----------------------------------------------------------------*/
6163 modified this code, but it doesn't appear to ever get called
6166 static void genOrOp (iCode *ic)
6168 operand *left,*right, *result;
6171 /* note here that || operations that are in an
6172 if statement are taken away by backPatchLabels
6173 only those used in arthmetic operations remain */
6174 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6175 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6176 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6177 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6179 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6181 /* if both are bit variables */
6182 if (AOP_TYPE(left) == AOP_CRY &&
6183 AOP_TYPE(right) == AOP_CRY ) {
6184 pic16_emitcode("clrc","");
6185 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6186 AOP(left)->aopu.aop_dir,
6187 AOP(left)->aopu.aop_dir);
6188 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6189 AOP(right)->aopu.aop_dir,
6190 AOP(right)->aopu.aop_dir);
6191 pic16_emitcode("setc","");
6194 tlbl = newiTempLabel(NULL);
6195 pic16_toBoolean(left);
6197 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
6198 pic16_toBoolean(right);
6199 pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
6201 pic16_outBitAcc(result);
6204 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6205 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6206 pic16_freeAsmop(result,NULL,ic,TRUE);
6209 /*-----------------------------------------------------------------*/
6210 /* isLiteralBit - test if lit == 2^n */
6211 /*-----------------------------------------------------------------*/
6212 static int isLiteralBit(unsigned long lit)
6214 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6215 0x100L,0x200L,0x400L,0x800L,
6216 0x1000L,0x2000L,0x4000L,0x8000L,
6217 0x10000L,0x20000L,0x40000L,0x80000L,
6218 0x100000L,0x200000L,0x400000L,0x800000L,
6219 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6220 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6223 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6224 for(idx = 0; idx < 32; idx++)
6230 /*-----------------------------------------------------------------*/
6231 /* continueIfTrue - */
6232 /*-----------------------------------------------------------------*/
6233 static void continueIfTrue (iCode *ic)
6235 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6237 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6241 /*-----------------------------------------------------------------*/
6243 /*-----------------------------------------------------------------*/
6244 static void jumpIfTrue (iCode *ic)
6246 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6248 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6252 /*-----------------------------------------------------------------*/
6253 /* jmpTrueOrFalse - */
6254 /*-----------------------------------------------------------------*/
6255 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6257 // ugly but optimized by peephole
6258 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6260 symbol *nlbl = newiTempLabel(NULL);
6261 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
6262 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6263 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6264 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6267 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6268 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6273 /*-----------------------------------------------------------------*/
6274 /* genAnd - code for and */
6275 /*-----------------------------------------------------------------*/
6276 static void genAnd (iCode *ic, iCode *ifx)
6278 operand *left, *right, *result;
6280 unsigned long lit = 0L;
6285 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6286 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6287 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6288 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6290 resolveIfx(&rIfx,ifx);
6292 /* if left is a literal & right is not then exchange them */
6293 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6294 AOP_NEEDSACC(left)) {
6295 operand *tmp = right ;
6300 /* if result = right then exchange them */
6301 if(pic16_sameRegs(AOP(result),AOP(right))){
6302 operand *tmp = right ;
6307 /* if right is bit then exchange them */
6308 if (AOP_TYPE(right) == AOP_CRY &&
6309 AOP_TYPE(left) != AOP_CRY){
6310 operand *tmp = right ;
6314 if(AOP_TYPE(right) == AOP_LIT)
6315 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6317 size = AOP_SIZE(result);
6319 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6322 // result = bit & yy;
6323 if (AOP_TYPE(left) == AOP_CRY){
6324 // c = bit & literal;
6325 if(AOP_TYPE(right) == AOP_LIT){
6327 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6330 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6333 if(size && (AOP_TYPE(result) == AOP_CRY)){
6334 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6337 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6341 pic16_emitcode("clr","c");
6344 if (AOP_TYPE(right) == AOP_CRY){
6346 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6347 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6350 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6352 pic16_emitcode("rrc","a");
6353 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6359 pic16_outBitC(result);
6361 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6362 genIfxJump(ifx, "c");
6366 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6367 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6368 if((AOP_TYPE(right) == AOP_LIT) &&
6369 (AOP_TYPE(result) == AOP_CRY) &&
6370 (AOP_TYPE(left) != AOP_CRY)){
6371 int posbit = isLiteralBit(lit);
6375 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6378 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6384 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6385 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6387 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6388 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6391 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6392 size = AOP_SIZE(left);
6395 int bp = posbit, ofs=0;
6402 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6403 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0));
6407 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6408 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6410 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6417 symbol *tlbl = newiTempLabel(NULL);
6418 int sizel = AOP_SIZE(left);
6420 pic16_emitcode("setb","c");
6422 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6423 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6425 if((posbit = isLiteralBit(bytelit)) != 0)
6426 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6428 if(bytelit != 0x0FFL)
6429 pic16_emitcode("anl","a,%s",
6430 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6431 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6436 // bit = left & literal
6438 pic16_emitcode("clr","c");
6439 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6441 // if(left & literal)
6444 jmpTrueOrFalse(ifx, tlbl);
6448 pic16_outBitC(result);
6452 /* if left is same as result */
6453 if(pic16_sameRegs(AOP(result),AOP(left))){
6455 for(;size--; offset++,lit>>=8) {
6456 if(AOP_TYPE(right) == AOP_LIT){
6457 switch(lit & 0xff) {
6459 /* and'ing with 0 has clears the result */
6460 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6461 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6464 /* and'ing with 0xff is a nop when the result and left are the same */
6469 int p = my_powof2( (~lit) & 0xff );
6471 /* only one bit is set in the literal, so use a bcf instruction */
6472 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6473 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6476 pic16_emitcode("movlw","0x%x", (lit & 0xff));
6477 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6478 if(know_W != (lit&0xff))
6479 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6481 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6486 if (AOP_TYPE(left) == AOP_ACC) {
6487 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6489 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6490 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6497 // left & result in different registers
6498 if(AOP_TYPE(result) == AOP_CRY){
6500 // if(size), result in bit
6501 // if(!size && ifx), conditional oper: if(left & right)
6502 symbol *tlbl = newiTempLabel(NULL);
6503 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6505 pic16_emitcode("setb","c");
6507 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6508 pic16_emitcode("anl","a,%s",
6509 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6510 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6515 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6516 pic16_outBitC(result);
6518 jmpTrueOrFalse(ifx, tlbl);
6520 for(;(size--);offset++) {
6522 // result = left & right
6523 if(AOP_TYPE(right) == AOP_LIT){
6524 int t = (lit >> (offset*8)) & 0x0FFL;
6527 pic16_emitcode("clrf","%s",
6528 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6529 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6532 pic16_emitcode("movf","%s,w",
6533 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6534 pic16_emitcode("movwf","%s",
6535 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6536 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6537 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6540 pic16_emitcode("movlw","0x%x",t);
6541 pic16_emitcode("andwf","%s,w",
6542 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6543 pic16_emitcode("movwf","%s",
6544 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6546 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6547 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6548 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6553 if (AOP_TYPE(left) == AOP_ACC) {
6554 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6555 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6557 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6558 pic16_emitcode("andwf","%s,w",
6559 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6560 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6561 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6563 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6564 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6570 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6571 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6572 pic16_freeAsmop(result,NULL,ic,TRUE);
6575 /*-----------------------------------------------------------------*/
6576 /* genOr - code for or */
6577 /*-----------------------------------------------------------------*/
6578 static void genOr (iCode *ic, iCode *ifx)
6580 operand *left, *right, *result;
6582 unsigned long lit = 0L;
6584 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6586 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6587 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6588 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6590 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6592 /* if left is a literal & right is not then exchange them */
6593 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6594 AOP_NEEDSACC(left)) {
6595 operand *tmp = right ;
6600 /* if result = right then exchange them */
6601 if(pic16_sameRegs(AOP(result),AOP(right))){
6602 operand *tmp = right ;
6607 /* if right is bit then exchange them */
6608 if (AOP_TYPE(right) == AOP_CRY &&
6609 AOP_TYPE(left) != AOP_CRY){
6610 operand *tmp = right ;
6615 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6617 if(AOP_TYPE(right) == AOP_LIT)
6618 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6620 size = AOP_SIZE(result);
6624 if (AOP_TYPE(left) == AOP_CRY){
6625 if(AOP_TYPE(right) == AOP_LIT){
6626 // c = bit & literal;
6628 // lit != 0 => result = 1
6629 if(AOP_TYPE(result) == AOP_CRY){
6631 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6632 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6633 // AOP(result)->aopu.aop_dir,
6634 // AOP(result)->aopu.aop_dir);
6636 continueIfTrue(ifx);
6640 // lit == 0 => result = left
6641 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6643 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6646 if (AOP_TYPE(right) == AOP_CRY){
6647 if(pic16_sameRegs(AOP(result),AOP(left))){
6649 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6650 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6651 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6653 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6654 AOP(result)->aopu.aop_dir,
6655 AOP(result)->aopu.aop_dir);
6656 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6657 AOP(right)->aopu.aop_dir,
6658 AOP(right)->aopu.aop_dir);
6659 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6660 AOP(result)->aopu.aop_dir,
6661 AOP(result)->aopu.aop_dir);
6663 if( AOP_TYPE(result) == AOP_ACC) {
6664 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6665 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6666 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6667 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6671 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6672 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6673 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6674 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6676 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6677 AOP(result)->aopu.aop_dir,
6678 AOP(result)->aopu.aop_dir);
6679 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6680 AOP(right)->aopu.aop_dir,
6681 AOP(right)->aopu.aop_dir);
6682 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6683 AOP(left)->aopu.aop_dir,
6684 AOP(left)->aopu.aop_dir);
6685 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6686 AOP(result)->aopu.aop_dir,
6687 AOP(result)->aopu.aop_dir);
6692 symbol *tlbl = newiTempLabel(NULL);
6693 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6696 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6697 if( AOP_TYPE(right) == AOP_ACC) {
6698 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6700 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6701 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6706 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6707 pic16_emitcode(";XXX setb","c");
6708 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6709 AOP(left)->aopu.aop_dir,tlbl->key+100);
6710 pic16_toBoolean(right);
6711 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6712 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6713 jmpTrueOrFalse(ifx, tlbl);
6717 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6724 pic16_outBitC(result);
6726 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6727 genIfxJump(ifx, "c");
6731 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6732 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6733 if((AOP_TYPE(right) == AOP_LIT) &&
6734 (AOP_TYPE(result) == AOP_CRY) &&
6735 (AOP_TYPE(left) != AOP_CRY)){
6737 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6740 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6742 continueIfTrue(ifx);
6745 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6746 // lit = 0, result = boolean(left)
6748 pic16_emitcode(";XXX setb","c");
6749 pic16_toBoolean(right);
6751 symbol *tlbl = newiTempLabel(NULL);
6752 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6754 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6756 genIfxJump (ifx,"a");
6760 pic16_outBitC(result);
6764 /* if left is same as result */
6765 if(pic16_sameRegs(AOP(result),AOP(left))){
6767 for(;size--; offset++,lit>>=8) {
6768 if(AOP_TYPE(right) == AOP_LIT){
6769 if((lit & 0xff) == 0)
6770 /* or'ing with 0 has no effect */
6773 int p = my_powof2(lit & 0xff);
6775 /* only one bit is set in the literal, so use a bsf instruction */
6776 pic16_emitpcode(POC_BSF,
6777 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6779 if(know_W != (lit & 0xff))
6780 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6781 know_W = lit & 0xff;
6782 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6787 if (AOP_TYPE(left) == AOP_ACC) {
6788 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
6789 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6791 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6792 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6794 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6795 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6801 // left & result in different registers
6802 if(AOP_TYPE(result) == AOP_CRY){
6804 // if(size), result in bit
6805 // if(!size && ifx), conditional oper: if(left | right)
6806 symbol *tlbl = newiTempLabel(NULL);
6807 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6808 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6812 pic16_emitcode(";XXX setb","c");
6814 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6815 pic16_emitcode(";XXX orl","a,%s",
6816 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6817 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6822 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6823 pic16_outBitC(result);
6825 jmpTrueOrFalse(ifx, tlbl);
6826 } else for(;(size--);offset++){
6828 // result = left & right
6829 if(AOP_TYPE(right) == AOP_LIT){
6830 int t = (lit >> (offset*8)) & 0x0FFL;
6833 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
6834 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6836 pic16_emitcode("movf","%s,w",
6837 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6838 pic16_emitcode("movwf","%s",
6839 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6842 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6843 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6844 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6846 pic16_emitcode("movlw","0x%x",t);
6847 pic16_emitcode("iorwf","%s,w",
6848 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6849 pic16_emitcode("movwf","%s",
6850 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6856 // faster than result <- left, anl result,right
6857 // and better if result is SFR
6858 if (AOP_TYPE(left) == AOP_ACC) {
6859 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
6860 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6862 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6863 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6865 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6866 pic16_emitcode("iorwf","%s,w",
6867 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6869 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6870 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6875 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6876 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6877 pic16_freeAsmop(result,NULL,ic,TRUE);
6880 /*-----------------------------------------------------------------*/
6881 /* genXor - code for xclusive or */
6882 /*-----------------------------------------------------------------*/
6883 static void genXor (iCode *ic, iCode *ifx)
6885 operand *left, *right, *result;
6887 unsigned long lit = 0L;
6889 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6891 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6892 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6893 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6895 /* if left is a literal & right is not ||
6896 if left needs acc & right does not */
6897 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6898 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6899 operand *tmp = right ;
6904 /* if result = right then exchange them */
6905 if(pic16_sameRegs(AOP(result),AOP(right))){
6906 operand *tmp = right ;
6911 /* if right is bit then exchange them */
6912 if (AOP_TYPE(right) == AOP_CRY &&
6913 AOP_TYPE(left) != AOP_CRY){
6914 operand *tmp = right ;
6918 if(AOP_TYPE(right) == AOP_LIT)
6919 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6921 size = AOP_SIZE(result);
6925 if (AOP_TYPE(left) == AOP_CRY){
6926 if(AOP_TYPE(right) == AOP_LIT){
6927 // c = bit & literal;
6929 // lit>>1 != 0 => result = 1
6930 if(AOP_TYPE(result) == AOP_CRY){
6932 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
6933 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6935 continueIfTrue(ifx);
6938 pic16_emitcode("setb","c");
6942 // lit == 0, result = left
6943 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6945 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6947 // lit == 1, result = not(left)
6948 if(size && pic16_sameRegs(AOP(result),AOP(left))){
6949 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
6950 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
6951 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6954 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6955 pic16_emitcode("cpl","c");
6962 symbol *tlbl = newiTempLabel(NULL);
6963 if (AOP_TYPE(right) == AOP_CRY){
6965 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6968 int sizer = AOP_SIZE(right);
6970 // if val>>1 != 0, result = 1
6971 pic16_emitcode("setb","c");
6973 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6975 // test the msb of the lsb
6976 pic16_emitcode("anl","a,#0xfe");
6977 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6981 pic16_emitcode("rrc","a");
6983 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6984 pic16_emitcode("cpl","c");
6985 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6990 pic16_outBitC(result);
6992 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6993 genIfxJump(ifx, "c");
6997 if(pic16_sameRegs(AOP(result),AOP(left))){
6998 /* if left is same as result */
6999 for(;size--; offset++) {
7000 if(AOP_TYPE(right) == AOP_LIT){
7001 int t = (lit >> (offset*8)) & 0x0FFL;
7005 if (IS_AOP_PREG(left)) {
7006 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7007 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7008 pic16_aopPut(AOP(result),"a",offset);
7010 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7011 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7012 pic16_emitcode("xrl","%s,%s",
7013 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7014 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7017 if (AOP_TYPE(left) == AOP_ACC)
7018 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7020 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7021 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7023 if (IS_AOP_PREG(left)) {
7024 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7025 pic16_aopPut(AOP(result),"a",offset);
7027 pic16_emitcode("xrl","%s,a",
7028 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7034 // left & result in different registers
7035 if(AOP_TYPE(result) == AOP_CRY){
7037 // if(size), result in bit
7038 // if(!size && ifx), conditional oper: if(left ^ right)
7039 symbol *tlbl = newiTempLabel(NULL);
7040 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7042 pic16_emitcode("setb","c");
7044 if((AOP_TYPE(right) == AOP_LIT) &&
7045 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7046 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7048 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7049 pic16_emitcode("xrl","a,%s",
7050 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7052 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7057 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7058 pic16_outBitC(result);
7060 jmpTrueOrFalse(ifx, tlbl);
7061 } else for(;(size--);offset++){
7063 // result = left & right
7064 if(AOP_TYPE(right) == AOP_LIT){
7065 int t = (lit >> (offset*8)) & 0x0FFL;
7068 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7069 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7070 pic16_emitcode("movf","%s,w",
7071 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7072 pic16_emitcode("movwf","%s",
7073 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7076 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7077 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7078 pic16_emitcode("comf","%s,w",
7079 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7080 pic16_emitcode("movwf","%s",
7081 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7084 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7085 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7086 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7087 pic16_emitcode("movlw","0x%x",t);
7088 pic16_emitcode("xorwf","%s,w",
7089 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7090 pic16_emitcode("movwf","%s",
7091 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7097 // faster than result <- left, anl result,right
7098 // and better if result is SFR
7099 if (AOP_TYPE(left) == AOP_ACC) {
7100 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7101 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7103 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7104 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7105 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7106 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7108 if ( AOP_TYPE(result) != AOP_ACC){
7109 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7110 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7116 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7117 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7118 pic16_freeAsmop(result,NULL,ic,TRUE);
7121 /*-----------------------------------------------------------------*/
7122 /* genInline - write the inline code out */
7123 /*-----------------------------------------------------------------*/
7124 static void genInline (iCode *ic)
7126 char *buffer, *bp, *bp1;
7128 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7130 _G.inLine += (!options.asmpeep);
7132 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7133 strcpy(buffer,IC_INLINE(ic));
7135 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7137 /* emit each line as a code */
7143 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7151 /* print label, use this special format with NULL directive
7152 * to denote that the argument should not be indented with tab */
7153 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7160 if ((bp1 != bp) && *bp1)
7161 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7166 _G.inLine -= (!options.asmpeep);
7169 /*-----------------------------------------------------------------*/
7170 /* genRRC - rotate right with carry */
7171 /*-----------------------------------------------------------------*/
7172 static void genRRC (iCode *ic)
7174 operand *left , *result ;
7175 int size, offset = 0, same;
7177 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7179 /* rotate right with carry */
7181 result=IC_RESULT(ic);
7182 pic16_aopOp (left,ic,FALSE);
7183 pic16_aopOp (result,ic,FALSE);
7185 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7187 same = pic16_sameRegs(AOP(result),AOP(left));
7189 size = AOP_SIZE(result);
7191 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7193 /* get the lsb and put it into the carry */
7194 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7201 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7203 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7204 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7210 pic16_freeAsmop(left,NULL,ic,TRUE);
7211 pic16_freeAsmop(result,NULL,ic,TRUE);
7214 /*-----------------------------------------------------------------*/
7215 /* genRLC - generate code for rotate left with carry */
7216 /*-----------------------------------------------------------------*/
7217 static void genRLC (iCode *ic)
7219 operand *left , *result ;
7220 int size, offset = 0;
7223 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7224 /* rotate right with carry */
7226 result=IC_RESULT(ic);
7227 pic16_aopOp (left,ic,FALSE);
7228 pic16_aopOp (result,ic,FALSE);
7230 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7232 same = pic16_sameRegs(AOP(result),AOP(left));
7234 /* move it to the result */
7235 size = AOP_SIZE(result);
7237 /* get the msb and put it into the carry */
7238 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7245 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7247 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7248 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7255 pic16_freeAsmop(left,NULL,ic,TRUE);
7256 pic16_freeAsmop(result,NULL,ic,TRUE);
7260 /* gpasm can get the highest order bit with HIGH/UPPER
7261 * so the following probably is not needed -- VR */
7263 /*-----------------------------------------------------------------*/
7264 /* genGetHbit - generates code get highest order bit */
7265 /*-----------------------------------------------------------------*/
7266 static void genGetHbit (iCode *ic)
7268 operand *left, *result;
7270 result=IC_RESULT(ic);
7271 pic16_aopOp (left,ic,FALSE);
7272 pic16_aopOp (result,ic,FALSE);
7274 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7275 /* get the highest order byte into a */
7276 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7277 if(AOP_TYPE(result) == AOP_CRY){
7278 pic16_emitcode("rlc","a");
7279 pic16_outBitC(result);
7282 pic16_emitcode("rl","a");
7283 pic16_emitcode("anl","a,#0x01");
7284 pic16_outAcc(result);
7288 pic16_freeAsmop(left,NULL,ic,TRUE);
7289 pic16_freeAsmop(result,NULL,ic,TRUE);
7293 /*-----------------------------------------------------------------*/
7294 /* AccRol - rotate left accumulator by known count */
7295 /*-----------------------------------------------------------------*/
7296 static void AccRol (int shCount)
7298 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7299 shCount &= 0x0007; // shCount : 0..7
7304 pic16_emitcode("rl","a");
7307 pic16_emitcode("rl","a");
7308 pic16_emitcode("rl","a");
7311 pic16_emitcode("swap","a");
7312 pic16_emitcode("rr","a");
7315 pic16_emitcode("swap","a");
7318 pic16_emitcode("swap","a");
7319 pic16_emitcode("rl","a");
7322 pic16_emitcode("rr","a");
7323 pic16_emitcode("rr","a");
7326 pic16_emitcode("rr","a");
7332 /*-----------------------------------------------------------------*/
7333 /* AccLsh - left shift accumulator by known count */
7334 /*-----------------------------------------------------------------*/
7335 static void AccLsh (int shCount)
7337 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7343 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7346 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7347 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7350 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7351 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7354 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7357 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7358 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7361 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7362 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7365 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7369 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7372 /*-----------------------------------------------------------------*/
7373 /* AccRsh - right shift accumulator by known count */
7374 /*-----------------------------------------------------------------*/
7375 static void AccRsh (int shCount, int andmask)
7377 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7382 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7383 // andmask = 0; /* no need */
7386 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7387 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7388 // andmask = 0; /* no need */
7391 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7392 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7395 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7398 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7399 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7402 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7403 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7406 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7411 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7413 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7417 /*-----------------------------------------------------------------*/
7418 /* AccSRsh - signed right shift accumulator by known count */
7419 /*-----------------------------------------------------------------*/
7420 static void AccSRsh (int shCount)
7423 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7426 pic16_emitcode("mov","c,acc.7");
7427 pic16_emitcode("rrc","a");
7428 } else if(shCount == 2){
7429 pic16_emitcode("mov","c,acc.7");
7430 pic16_emitcode("rrc","a");
7431 pic16_emitcode("mov","c,acc.7");
7432 pic16_emitcode("rrc","a");
7434 tlbl = newiTempLabel(NULL);
7435 /* rotate right accumulator */
7436 AccRol(8 - shCount);
7437 /* and kill the higher order bits */
7438 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7439 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7440 pic16_emitcode("orl","a,#0x%02x",
7441 (unsigned char)~SRMask[shCount]);
7442 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7447 /*-----------------------------------------------------------------*/
7448 /* shiftR1Left2Result - shift right one byte from left to result */
7449 /*-----------------------------------------------------------------*/
7450 static void shiftR1Left2ResultSigned (operand *left, int offl,
7451 operand *result, int offr,
7456 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7458 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7462 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7464 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7466 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7467 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7473 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7475 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7477 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7478 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7480 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7481 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7487 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7489 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7490 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7493 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7494 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7495 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7497 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7498 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7500 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7504 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7505 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7506 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7507 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
7508 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7512 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7514 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7515 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7517 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7518 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
7519 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7520 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
7521 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7526 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7527 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7528 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7529 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7530 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7531 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7533 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7534 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7535 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7536 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7537 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7543 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7544 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7545 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7546 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7548 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7549 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7550 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7558 /*-----------------------------------------------------------------*/
7559 /* shiftR1Left2Result - shift right one byte from left to result */
7560 /*-----------------------------------------------------------------*/
7561 static void shiftR1Left2Result (operand *left, int offl,
7562 operand *result, int offr,
7563 int shCount, int sign)
7567 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7569 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7571 /* Copy the msb into the carry if signed. */
7573 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7583 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7585 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7586 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7592 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7594 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7595 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7598 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7603 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7605 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7606 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7609 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7610 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7611 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7612 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7616 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7617 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7618 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7622 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7623 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7624 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7626 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7631 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7632 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7633 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7634 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7635 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7640 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7641 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7642 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7651 /*-----------------------------------------------------------------*/
7652 /* shiftL1Left2Result - shift left one byte from left to result */
7653 /*-----------------------------------------------------------------*/
7654 static void shiftL1Left2Result (operand *left, int offl,
7655 operand *result, int offr, int shCount)
7660 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7662 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7663 DEBUGpic16_emitcode ("; ***","same = %d",same);
7664 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7666 /* shift left accumulator */
7667 //AccLsh(shCount); // don't comment out just yet...
7668 // pic16_aopPut(AOP(result),"a",offr);
7672 /* Shift left 1 bit position */
7673 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7675 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7677 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7678 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7682 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7683 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7684 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7685 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7688 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7689 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7690 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7691 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7692 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7695 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7696 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7697 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7700 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7701 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7702 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7703 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7706 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7707 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7708 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7709 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7710 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7713 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7714 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7715 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7719 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7724 /*-----------------------------------------------------------------*/
7725 /* movLeft2Result - move byte from left to result */
7726 /*-----------------------------------------------------------------*/
7727 static void movLeft2Result (operand *left, int offl,
7728 operand *result, int offr)
7731 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7732 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7733 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7735 if (*l == '@' && (IS_AOP_PREG(result))) {
7736 pic16_emitcode("mov","a,%s",l);
7737 pic16_aopPut(AOP(result),"a",offr);
7739 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7740 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7745 /*-----------------------------------------------------------------*/
7746 /* shiftL2Left2Result - shift left two bytes from left to result */
7747 /*-----------------------------------------------------------------*/
7748 static void shiftL2Left2Result (operand *left, int offl,
7749 operand *result, int offr, int shCount)
7751 int same = pic16_sameRegs(AOP(result), AOP(left));
7754 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7756 if (same && (offl != offr)) { // shift bytes
7759 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7760 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7762 } else { // just treat as different later on
7775 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7776 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7777 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7781 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7782 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7788 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7789 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7790 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7791 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7792 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7793 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7794 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7796 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7797 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7801 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7802 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7803 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7804 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7805 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7806 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7807 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7808 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7809 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7810 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7813 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7814 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7815 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7816 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7817 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7827 /* note, use a mov/add for the shift since the mov has a
7828 chance of getting optimized out */
7829 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7830 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7831 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7832 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7833 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7837 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7838 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7844 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7845 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7846 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7847 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7848 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7849 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7850 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7851 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7855 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7856 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7860 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7861 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7862 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7863 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7865 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7866 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7867 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7868 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7869 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7870 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7871 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7872 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7875 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7876 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7877 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7878 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7879 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7884 /*-----------------------------------------------------------------*/
7885 /* shiftR2Left2Result - shift right two bytes from left to result */
7886 /*-----------------------------------------------------------------*/
7887 static void shiftR2Left2Result (operand *left, int offl,
7888 operand *result, int offr,
7889 int shCount, int sign)
7891 int same = pic16_sameRegs(AOP(result), AOP(left));
7893 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7895 if (same && (offl != offr)) { // shift right bytes
7898 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7899 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7901 } else { // just treat as different later on
7913 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7918 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7919 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7921 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7922 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7923 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7924 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7929 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7932 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7933 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7940 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7941 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7942 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7944 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7945 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7946 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7947 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7949 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7950 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7951 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7953 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7954 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7955 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7956 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7957 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7961 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7962 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7966 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7967 pic16_emitpcode(POC_BTFSC,
7968 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7969 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7977 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7978 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7980 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7981 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7982 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7983 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7985 pic16_emitpcode(POC_BTFSC,
7986 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7987 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7989 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7990 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7991 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7992 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7994 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7995 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7996 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7997 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7998 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7999 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8000 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8001 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8003 pic16_emitpcode(POC_BTFSC,
8004 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
8005 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8007 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8008 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8015 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8016 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8017 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8018 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8021 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8023 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8028 /*-----------------------------------------------------------------*/
8029 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8030 /*-----------------------------------------------------------------*/
8031 static void shiftLLeftOrResult (operand *left, int offl,
8032 operand *result, int offr, int shCount)
8034 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8036 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8037 /* shift left accumulator */
8039 /* or with result */
8040 /* back to result */
8041 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8044 /*-----------------------------------------------------------------*/
8045 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8046 /*-----------------------------------------------------------------*/
8047 static void shiftRLeftOrResult (operand *left, int offl,
8048 operand *result, int offr, int shCount)
8050 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8052 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8053 /* shift right accumulator */
8055 /* or with result */
8056 /* back to result */
8057 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8060 /*-----------------------------------------------------------------*/
8061 /* genlshOne - left shift a one byte quantity by known count */
8062 /*-----------------------------------------------------------------*/
8063 static void genlshOne (operand *result, operand *left, int shCount)
8065 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8066 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8069 /*-----------------------------------------------------------------*/
8070 /* genlshTwo - left shift two bytes by known amount != 0 */
8071 /*-----------------------------------------------------------------*/
8072 static void genlshTwo (operand *result,operand *left, int shCount)
8076 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8077 size = pic16_getDataSize(result);
8079 /* if shCount >= 8 */
8085 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8087 movLeft2Result(left, LSB, result, MSB16);
8089 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8092 /* 1 <= shCount <= 7 */
8095 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8097 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8101 /*-----------------------------------------------------------------*/
8102 /* shiftLLong - shift left one long from left to result */
8103 /* offr = LSB or MSB16 */
8104 /*-----------------------------------------------------------------*/
8105 static void shiftLLong (operand *left, operand *result, int offr )
8107 int size = AOP_SIZE(result);
8108 int same = pic16_sameRegs(AOP(left),AOP(result));
8111 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8113 if (same && (offr == MSB16)) { //shift one byte
8114 for(i=size-1;i>=MSB16;i--) {
8115 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8116 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8119 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8122 if (size >= LSB+offr ){
8124 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8126 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8127 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8131 if(size >= MSB16+offr){
8133 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8135 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8136 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8140 if(size >= MSB24+offr){
8142 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8144 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8145 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8149 if(size > MSB32+offr){
8151 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8153 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8154 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8158 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8162 /*-----------------------------------------------------------------*/
8163 /* genlshFour - shift four byte by a known amount != 0 */
8164 /*-----------------------------------------------------------------*/
8165 static void genlshFour (operand *result, operand *left, int shCount)
8169 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8170 size = AOP_SIZE(result);
8172 /* if shifting more that 3 bytes */
8173 if (shCount >= 24 ) {
8176 /* lowest order of left goes to the highest
8177 order of the destination */
8178 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8180 movLeft2Result(left, LSB, result, MSB32);
8182 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8183 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8184 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8189 /* more than two bytes */
8190 else if ( shCount >= 16 ) {
8191 /* lower order two bytes goes to higher order two bytes */
8193 /* if some more remaining */
8195 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8197 movLeft2Result(left, MSB16, result, MSB32);
8198 movLeft2Result(left, LSB, result, MSB24);
8200 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8201 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8205 /* if more than 1 byte */
8206 else if ( shCount >= 8 ) {
8207 /* lower order three bytes goes to higher order three bytes */
8211 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8213 movLeft2Result(left, LSB, result, MSB16);
8215 else{ /* size = 4 */
8217 movLeft2Result(left, MSB24, result, MSB32);
8218 movLeft2Result(left, MSB16, result, MSB24);
8219 movLeft2Result(left, LSB, result, MSB16);
8220 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8222 else if(shCount == 1)
8223 shiftLLong(left, result, MSB16);
8225 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8226 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8227 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8228 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8233 /* 1 <= shCount <= 7 */
8234 else if(shCount <= 3)
8236 shiftLLong(left, result, LSB);
8237 while(--shCount >= 1)
8238 shiftLLong(result, result, LSB);
8240 /* 3 <= shCount <= 7, optimize */
8242 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8243 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8244 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8248 /*-----------------------------------------------------------------*/
8249 /* genLeftShiftLiteral - left shifting by known count */
8250 /*-----------------------------------------------------------------*/
8251 static void genLeftShiftLiteral (operand *left,
8256 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8259 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8260 pic16_freeAsmop(right,NULL,ic,TRUE);
8262 pic16_aopOp(left,ic,FALSE);
8263 pic16_aopOp(result,ic,FALSE);
8265 size = getSize(operandType(result));
8268 pic16_emitcode("; shift left ","result %d, left %d",size,
8272 /* I suppose that the left size >= result size */
8275 movLeft2Result(left, size, result, size);
8279 else if(shCount >= (size * 8))
8281 pic16_aopPut(AOP(result),zero,size);
8285 genlshOne (result,left,shCount);
8290 genlshTwo (result,left,shCount);
8294 genlshFour (result,left,shCount);
8298 pic16_freeAsmop(left,NULL,ic,TRUE);
8299 pic16_freeAsmop(result,NULL,ic,TRUE);
8302 /*-----------------------------------------------------------------*
8303 * genMultiAsm - repeat assembly instruction for size of register.
8304 * if endian == 1, then the high byte (i.e base address + size of
8305 * register) is used first else the low byte is used first;
8306 *-----------------------------------------------------------------*/
8307 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8312 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8325 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
8330 /*-----------------------------------------------------------------*/
8331 /* genLeftShift - generates code for left shifting */
8332 /*-----------------------------------------------------------------*/
8333 static void genLeftShift (iCode *ic)
8335 operand *left,*right, *result;
8338 symbol *tlbl , *tlbl1;
8341 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8343 right = IC_RIGHT(ic);
8345 result = IC_RESULT(ic);
8347 pic16_aopOp(right,ic,FALSE);
8349 /* if the shift count is known then do it
8350 as efficiently as possible */
8351 if (AOP_TYPE(right) == AOP_LIT) {
8352 genLeftShiftLiteral (left,right,result,ic);
8356 /* shift count is unknown then we have to form
8357 a loop get the loop count in B : Note: we take
8358 only the lower order byte since shifting
8359 more that 32 bits make no sense anyway, ( the
8360 largest size of an object can be only 32 bits ) */
8363 pic16_aopOp(left,ic,FALSE);
8364 pic16_aopOp(result,ic,FALSE);
8366 /* now move the left to the result if they are not the
8368 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8369 AOP_SIZE(result) > 1) {
8371 size = AOP_SIZE(result);
8374 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8375 if (*l == '@' && (IS_AOP_PREG(result))) {
8377 pic16_emitcode("mov","a,%s",l);
8378 pic16_aopPut(AOP(result),"a",offset);
8380 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8381 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8382 //pic16_aopPut(AOP(result),l,offset);
8388 size = AOP_SIZE(result);
8390 /* if it is only one byte then */
8392 if(optimized_for_speed) {
8393 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8394 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8395 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
8396 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8397 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8398 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
8399 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8400 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
8401 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
8402 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
8403 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
8404 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8407 tlbl = newiTempLabel(NULL);
8408 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8409 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8410 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8413 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8414 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8415 pic16_emitpLabel(tlbl->key);
8416 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8417 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8419 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8424 if (pic16_sameRegs(AOP(left),AOP(result))) {
8426 tlbl = newiTempLabel(NULL);
8427 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8428 genMultiAsm(POC_RRCF, result, size,1);
8429 pic16_emitpLabel(tlbl->key);
8430 genMultiAsm(POC_RLCF, result, size,0);
8431 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8433 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8437 //tlbl = newiTempLabel(NULL);
8439 //tlbl1 = newiTempLabel(NULL);
8441 //reAdjustPreg(AOP(result));
8443 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8444 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8445 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8447 //pic16_emitcode("add","a,acc");
8448 //pic16_aopPut(AOP(result),"a",offset++);
8450 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8452 // pic16_emitcode("rlc","a");
8453 // pic16_aopPut(AOP(result),"a",offset++);
8455 //reAdjustPreg(AOP(result));
8457 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8458 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8461 tlbl = newiTempLabel(NULL);
8462 tlbl1= newiTempLabel(NULL);
8464 size = AOP_SIZE(result);
8467 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8469 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8471 /* offset should be 0, 1 or 3 */
8473 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8475 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8477 pic16_emitpcode(POC_MOVWF, pctemp);
8480 pic16_emitpLabel(tlbl->key);
8483 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8485 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
8487 pic16_emitpcode(POC_DECFSZ, pctemp);
8488 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8489 pic16_emitpLabel(tlbl1->key);
8491 pic16_popReleaseTempReg(pctemp);
8495 pic16_freeAsmop (right,NULL,ic,TRUE);
8496 pic16_freeAsmop(left,NULL,ic,TRUE);
8497 pic16_freeAsmop(result,NULL,ic,TRUE);
8500 /*-----------------------------------------------------------------*/
8501 /* genrshOne - right shift a one byte quantity by known count */
8502 /*-----------------------------------------------------------------*/
8503 static void genrshOne (operand *result, operand *left,
8504 int shCount, int sign)
8506 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8507 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8510 /*-----------------------------------------------------------------*/
8511 /* genrshTwo - right shift two bytes by known amount != 0 */
8512 /*-----------------------------------------------------------------*/
8513 static void genrshTwo (operand *result,operand *left,
8514 int shCount, int sign)
8516 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8517 /* if shCount >= 8 */
8521 shiftR1Left2Result(left, MSB16, result, LSB,
8524 movLeft2Result(left, MSB16, result, LSB);
8526 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8529 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8530 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8534 /* 1 <= shCount <= 7 */
8536 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
8539 /*-----------------------------------------------------------------*/
8540 /* shiftRLong - shift right one long from left to result */
8541 /* offl = LSB or MSB16 */
8542 /*-----------------------------------------------------------------*/
8543 static void shiftRLong (operand *left, int offl,
8544 operand *result, int sign)
8546 int size = AOP_SIZE(result);
8547 int same = pic16_sameRegs(AOP(left),AOP(result));
8549 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8551 if (same && (offl == MSB16)) { //shift one byte right
8552 for(i=MSB16;i<size;i++) {
8553 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8554 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8559 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8565 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8567 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8568 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8572 /* add sign of "a" */
8573 pic16_addSign(result, MSB32, sign);
8577 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8579 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8580 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8584 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8586 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8587 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8591 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8594 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8595 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8600 /*-----------------------------------------------------------------*/
8601 /* genrshFour - shift four byte by a known amount != 0 */
8602 /*-----------------------------------------------------------------*/
8603 static void genrshFour (operand *result, operand *left,
8604 int shCount, int sign)
8606 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8607 /* if shifting more that 3 bytes */
8608 if(shCount >= 24 ) {
8611 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8613 movLeft2Result(left, MSB32, result, LSB);
8615 pic16_addSign(result, MSB16, sign);
8617 else if(shCount >= 16){
8620 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8622 movLeft2Result(left, MSB24, result, LSB);
8623 movLeft2Result(left, MSB32, result, MSB16);
8625 pic16_addSign(result, MSB24, sign);
8627 else if(shCount >= 8){
8630 shiftRLong(left, MSB16, result, sign);
8631 else if(shCount == 0){
8632 movLeft2Result(left, MSB16, result, LSB);
8633 movLeft2Result(left, MSB24, result, MSB16);
8634 movLeft2Result(left, MSB32, result, MSB24);
8635 pic16_addSign(result, MSB32, sign);
8637 else{ //shcount >= 2
8638 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8639 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8640 /* the last shift is signed */
8641 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8642 pic16_addSign(result, MSB32, sign);
8645 else{ /* 1 <= shCount <= 7 */
8647 shiftRLong(left, LSB, result, sign);
8649 shiftRLong(result, LSB, result, sign);
8652 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8653 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8654 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8659 /*-----------------------------------------------------------------*/
8660 /* genRightShiftLiteral - right shifting by known count */
8661 /*-----------------------------------------------------------------*/
8662 static void genRightShiftLiteral (operand *left,
8668 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8671 pic16_freeAsmop(right,NULL,ic,TRUE);
8673 pic16_aopOp(left,ic,FALSE);
8674 pic16_aopOp(result,ic,FALSE);
8676 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8679 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8683 lsize = pic16_getDataSize(left);
8684 res_size = pic16_getDataSize(result);
8685 /* test the LEFT size !!! */
8687 /* I suppose that the left size >= result size */
8690 movLeft2Result(left, lsize, result, res_size);
8693 else if(shCount >= (lsize * 8)){
8696 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8698 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8699 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8704 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8705 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8706 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8708 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8713 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8720 genrshOne (result,left,shCount,sign);
8724 genrshTwo (result,left,shCount,sign);
8728 genrshFour (result,left,shCount,sign);
8736 pic16_freeAsmop(left,NULL,ic,TRUE);
8737 pic16_freeAsmop(result,NULL,ic,TRUE);
8740 /*-----------------------------------------------------------------*/
8741 /* genSignedRightShift - right shift of signed number */
8742 /*-----------------------------------------------------------------*/
8743 static void genSignedRightShift (iCode *ic)
8745 operand *right, *left, *result;
8748 symbol *tlbl, *tlbl1 ;
8751 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8753 /* we do it the hard way put the shift count in b
8754 and loop thru preserving the sign */
8755 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8757 right = IC_RIGHT(ic);
8759 result = IC_RESULT(ic);
8761 pic16_aopOp(right,ic,FALSE);
8762 pic16_aopOp(left,ic,FALSE);
8763 pic16_aopOp(result,ic,FALSE);
8766 if ( AOP_TYPE(right) == AOP_LIT) {
8767 genRightShiftLiteral (left,right,result,ic,1);
8770 /* shift count is unknown then we have to form
8771 a loop get the loop count in B : Note: we take
8772 only the lower order byte since shifting
8773 more that 32 bits make no sense anyway, ( the
8774 largest size of an object can be only 32 bits ) */
8776 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8777 //pic16_emitcode("inc","b");
8778 //pic16_freeAsmop (right,NULL,ic,TRUE);
8779 //pic16_aopOp(left,ic,FALSE);
8780 //pic16_aopOp(result,ic,FALSE);
8782 /* now move the left to the result if they are not the
8784 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8785 AOP_SIZE(result) > 1) {
8787 size = AOP_SIZE(result);
8791 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8792 if (*l == '@' && IS_AOP_PREG(result)) {
8794 pic16_emitcode("mov","a,%s",l);
8795 pic16_aopPut(AOP(result),"a",offset);
8797 pic16_aopPut(AOP(result),l,offset);
8799 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8800 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8806 /* mov the highest order bit to OVR */
8807 tlbl = newiTempLabel(NULL);
8808 tlbl1= newiTempLabel(NULL);
8810 size = AOP_SIZE(result);
8813 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8815 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8817 /* offset should be 0, 1 or 3 */
8818 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8820 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8822 pic16_emitpcode(POC_MOVWF, pctemp);
8825 pic16_emitpLabel(tlbl->key);
8827 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
8828 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
8831 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
8834 pic16_emitpcode(POC_DECFSZ, pctemp);
8835 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8836 pic16_emitpLabel(tlbl1->key);
8838 pic16_popReleaseTempReg(pctemp);
8840 size = AOP_SIZE(result);
8842 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8843 pic16_emitcode("rlc","a");
8844 pic16_emitcode("mov","ov,c");
8845 /* if it is only one byte then */
8847 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8849 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8850 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8851 pic16_emitcode("mov","c,ov");
8852 pic16_emitcode("rrc","a");
8853 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8854 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8855 pic16_aopPut(AOP(result),"a",0);
8859 reAdjustPreg(AOP(result));
8860 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8861 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8862 pic16_emitcode("mov","c,ov");
8864 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8866 pic16_emitcode("rrc","a");
8867 pic16_aopPut(AOP(result),"a",offset--);
8869 reAdjustPreg(AOP(result));
8870 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8871 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8876 pic16_freeAsmop(left,NULL,ic,TRUE);
8877 pic16_freeAsmop(result,NULL,ic,TRUE);
8878 pic16_freeAsmop(right,NULL,ic,TRUE);
8881 /*-----------------------------------------------------------------*/
8882 /* genRightShift - generate code for right shifting */
8883 /*-----------------------------------------------------------------*/
8884 static void genRightShift (iCode *ic)
8886 operand *right, *left, *result;
8890 symbol *tlbl, *tlbl1 ;
8892 /* if signed then we do it the hard way preserve the
8893 sign bit moving it inwards */
8894 letype = getSpec(operandType(IC_LEFT(ic)));
8895 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8897 if (!SPEC_USIGN(letype)) {
8898 genSignedRightShift (ic);
8902 /* signed & unsigned types are treated the same : i.e. the
8903 signed is NOT propagated inwards : quoting from the
8904 ANSI - standard : "for E1 >> E2, is equivalent to division
8905 by 2**E2 if unsigned or if it has a non-negative value,
8906 otherwise the result is implementation defined ", MY definition
8907 is that the sign does not get propagated */
8909 right = IC_RIGHT(ic);
8911 result = IC_RESULT(ic);
8913 pic16_aopOp(right,ic,FALSE);
8915 /* if the shift count is known then do it
8916 as efficiently as possible */
8917 if (AOP_TYPE(right) == AOP_LIT) {
8918 genRightShiftLiteral (left,right,result,ic, 0);
8922 /* shift count is unknown then we have to form
8923 a loop get the loop count in B : Note: we take
8924 only the lower order byte since shifting
8925 more that 32 bits make no sense anyway, ( the
8926 largest size of an object can be only 32 bits ) */
8928 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8929 pic16_emitcode("inc","b");
8930 pic16_aopOp(left,ic,FALSE);
8931 pic16_aopOp(result,ic,FALSE);
8933 /* now move the left to the result if they are not the
8935 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8936 AOP_SIZE(result) > 1) {
8938 size = AOP_SIZE(result);
8941 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8942 if (*l == '@' && IS_AOP_PREG(result)) {
8944 pic16_emitcode("mov","a,%s",l);
8945 pic16_aopPut(AOP(result),"a",offset);
8947 pic16_aopPut(AOP(result),l,offset);
8952 tlbl = newiTempLabel(NULL);
8953 tlbl1= newiTempLabel(NULL);
8954 size = AOP_SIZE(result);
8957 /* if it is only one byte then */
8960 tlbl = newiTempLabel(NULL);
8961 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8962 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8963 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8966 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8967 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8968 pic16_emitpLabel(tlbl->key);
8969 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8970 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8972 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8977 reAdjustPreg(AOP(result));
8978 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8979 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8982 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8984 pic16_emitcode("rrc","a");
8985 pic16_aopPut(AOP(result),"a",offset--);
8987 reAdjustPreg(AOP(result));
8989 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8990 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8993 pic16_freeAsmop(left,NULL,ic,TRUE);
8994 pic16_freeAsmop (right,NULL,ic,TRUE);
8995 pic16_freeAsmop(result,NULL,ic,TRUE);
8998 /*-----------------------------------------------------------------*/
8999 /* genUnpackBits - generates code for unpacking bits */
9000 /*-----------------------------------------------------------------*/
9001 static void genUnpackBits (operand *result, char *rname, int ptype)
9008 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9009 etype = getSpec(operandType(result));
9011 /* read the first byte */
9018 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9021 pic16_emitcode("clr","a");
9022 pic16_emitcode("movc","a","@a+dptr");
9027 /* if we have bitdisplacement then it fits */
9028 /* into this byte completely or if length is */
9029 /* less than a byte */
9030 if ((shCnt = SPEC_BSTR(etype)) ||
9031 (SPEC_BLEN(etype) <= 8)) {
9033 /* shift right acc */
9036 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9037 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9039 /* VR -- normally I would use the following, but since we use the hack,
9040 * to avoid the masking from AccRsh, why not mask it right now? */
9043 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9046 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9052 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9053 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9056 /* bit field did not fit in a byte */
9057 rlen = SPEC_BLEN(etype) - 8;
9058 pic16_aopPut(AOP(result),"a",offset++);
9065 pic16_emitcode("inc","%s",rname);
9066 pic16_emitcode("mov","a,@%s",rname);
9070 pic16_emitcode("inc","%s",rname);
9071 pic16_emitcode("movx","a,@%s",rname);
9075 pic16_emitcode("inc","dptr");
9076 pic16_emitcode("movx","a,@dptr");
9080 pic16_emitcode("clr","a");
9081 pic16_emitcode("inc","dptr");
9082 pic16_emitcode("movc","a","@a+dptr");
9086 pic16_emitcode("inc","dptr");
9087 pic16_emitcode("lcall","__gptrget");
9092 /* if we are done */
9096 pic16_aopPut(AOP(result),"a",offset++);
9101 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9102 pic16_aopPut(AOP(result),"a",offset);
9109 static void genDataPointerGet(operand *left,
9113 int size, offset = 0, leoffset=0 ;
9115 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9116 pic16_aopOp(result, ic, FALSE);
9118 size = AOP_SIZE(result);
9119 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9123 /* The following tests may save a redudant movff instruction when
9124 * accessing unions */
9126 /* if they are the same */
9127 if (operandsEqu (left, result)) {
9128 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9134 /* if they are the same registers */
9135 if (pic16_sameRegs(AOP(left),AOP(result))) {
9136 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9142 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9143 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9144 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9151 if ( AOP_TYPE(left) == AOP_PCODE) {
9152 fprintf(stderr,"genDataPointerGet %s, %d\n",
9153 AOP(left)->aopu.pcop->name,
9154 (AOP(left)->aopu.pcop->type == PO_DIR)?
9155 PCOR(AOP(left)->aopu.pcop)->instance:
9156 PCOI(AOP(left)->aopu.pcop)->offset);
9160 if(AOP(left)->aopu.pcop->type == PO_DIR)
9161 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9163 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9166 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9168 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9169 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9170 mov2w(AOP(left), offset); // patch 8
9171 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9173 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9174 pic16_popGet(AOP(left), offset), //patch 8
9175 pic16_popGet(AOP(result), offset)));
9183 pic16_freeAsmop(result,NULL,ic,TRUE);
9186 void pic16_loadFSR0(operand *op)
9188 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9192 /*-----------------------------------------------------------------*/
9193 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
9194 /*-----------------------------------------------------------------*/
9195 static void genNearPointerGet (operand *left,
9200 //regs *preg = NULL ;
9201 sym_link *rtype, *retype;
9202 sym_link *ltype = operandType(left);
9204 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9205 rtype = operandType(result);
9206 retype= getSpec(rtype);
9208 pic16_aopOp(left,ic,FALSE);
9210 // pic16_DumpOp("(left)",left);
9211 // pic16_DumpOp("(result)",result);
9213 /* if left is rematerialisable and
9214 * result is not bit variable type and
9215 * the left is pointer to data space i.e
9216 * lower 128 bytes of space */
9217 if (AOP_TYPE(left) == AOP_PCODE
9218 && !IS_BITFIELD(retype)
9219 && DCL_TYPE(ltype) == POINTER) {
9221 genDataPointerGet (left,result,ic);
9222 pic16_freeAsmop(left, NULL, ic, TRUE);
9226 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9228 /* if the value is already in a pointer register
9229 * then don't need anything more */
9230 if (!AOP_INPREG(AOP(left))) {
9231 /* otherwise get a free pointer register */
9232 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9234 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9235 if( (AOP_TYPE(left) == AOP_PCODE)
9236 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9237 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9239 pic16_loadFSR0( left ); // patch 10
9241 // set up FSR0 with address from left
9242 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9243 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9247 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9249 pic16_aopOp (result,ic,FALSE);
9251 /* if bitfield then unpack the bits */
9252 if (IS_BITFIELD(retype))
9253 genUnpackBits (result, NULL, POINTER);
9255 /* we have can just get the values */
9256 int size = AOP_SIZE(result);
9259 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9262 /* fsr0 is loaded already -- VR */
9263 // pic16_loadFSR0( left );
9265 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9266 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9270 pic16_emitpcode(POC_MOVFF,
9271 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9272 pic16_popGet(AOP(result), offset++)));
9274 pic16_emitpcode(POC_MOVFF,
9275 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9276 pic16_popGet(AOP(result), offset++)));
9280 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9281 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9283 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9287 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9289 pic16_emitcode("mov","a,@%s",rname);
9290 pic16_aopPut(AOP(result),"a",offset);
9292 sprintf(buffer,"@%s",rname);
9293 pic16_aopPut(AOP(result),buffer,offset);
9297 pic16_emitcode("inc","%s",rname);
9302 /* now some housekeeping stuff */
9304 /* we had to allocate for this iCode */
9305 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9306 pic16_freeAsmop(NULL,aop,ic,TRUE);
9308 /* we did not allocate which means left
9309 already in a pointer register, then
9310 if size > 0 && this could be used again
9311 we have to point it back to where it
9313 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9314 if (AOP_SIZE(result) > 1 &&
9315 !OP_SYMBOL(left)->remat &&
9316 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9318 // int size = AOP_SIZE(result) - 1;
9320 // pic16_emitcode("dec","%s",rname);
9325 pic16_freeAsmop(left,NULL,ic,TRUE);
9326 pic16_freeAsmop(result,NULL,ic,TRUE);
9330 /*-----------------------------------------------------------------*/
9331 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
9332 /*-----------------------------------------------------------------*/
9333 static void genPagedPointerGet (operand *left,
9340 sym_link *rtype, *retype;
9342 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9344 rtype = operandType(result);
9345 retype= getSpec(rtype);
9347 pic16_aopOp(left,ic,FALSE);
9349 /* if the value is already in a pointer register
9350 then don't need anything more */
9351 if (!AOP_INPREG(AOP(left))) {
9352 /* otherwise get a free pointer register */
9354 preg = getFreePtr(ic,&aop,FALSE);
9355 pic16_emitcode("mov","%s,%s",
9357 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9358 rname = preg->name ;
9360 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9362 pic16_freeAsmop(left,NULL,ic,TRUE);
9363 pic16_aopOp (result,ic,FALSE);
9365 /* if bitfield then unpack the bits */
9366 if (IS_BITFIELD(retype))
9367 genUnpackBits (result,rname,PPOINTER);
9369 /* we have can just get the values */
9370 int size = AOP_SIZE(result);
9375 pic16_emitcode("movx","a,@%s",rname);
9376 pic16_aopPut(AOP(result),"a",offset);
9381 pic16_emitcode("inc","%s",rname);
9385 /* now some housekeeping stuff */
9387 /* we had to allocate for this iCode */
9388 pic16_freeAsmop(NULL,aop,ic,TRUE);
9390 /* we did not allocate which means left
9391 already in a pointer register, then
9392 if size > 0 && this could be used again
9393 we have to point it back to where it
9395 if (AOP_SIZE(result) > 1 &&
9396 !OP_SYMBOL(left)->remat &&
9397 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9399 int size = AOP_SIZE(result) - 1;
9401 pic16_emitcode("dec","%s",rname);
9406 pic16_freeAsmop(result,NULL,ic,TRUE);
9411 /*-----------------------------------------------------------------*/
9412 /* genFarPointerGet - gget value from far space */
9413 /*-----------------------------------------------------------------*/
9414 static void genFarPointerGet (operand *left,
9415 operand *result, iCode *ic)
9418 sym_link *retype = getSpec(operandType(result));
9420 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9422 pic16_aopOp(left,ic,FALSE);
9424 /* if the operand is already in dptr
9425 then we do nothing else we move the value to dptr */
9426 if (AOP_TYPE(left) != AOP_STR) {
9427 /* if this is remateriazable */
9428 if (AOP_TYPE(left) == AOP_IMMD)
9429 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9430 else { /* we need to get it byte by byte */
9431 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9432 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9433 if (options.model == MODEL_FLAT24)
9435 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9439 /* so dptr know contains the address */
9440 pic16_freeAsmop(left,NULL,ic,TRUE);
9441 pic16_aopOp(result,ic,FALSE);
9443 /* if bit then unpack */
9444 if (IS_BITFIELD(retype))
9445 genUnpackBits(result,"dptr",FPOINTER);
9447 size = AOP_SIZE(result);
9451 pic16_emitcode("movx","a,@dptr");
9452 pic16_aopPut(AOP(result),"a",offset++);
9454 pic16_emitcode("inc","dptr");
9458 pic16_freeAsmop(result,NULL,ic,TRUE);
9461 /*-----------------------------------------------------------------*/
9462 /* genCodePointerGet - get value from code space */
9463 /*-----------------------------------------------------------------*/
9464 static void genCodePointerGet (operand *left,
9465 operand *result, iCode *ic)
9468 sym_link *retype = getSpec(operandType(result));
9470 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9472 pic16_aopOp(left,ic,FALSE);
9474 /* if the operand is already in dptr
9475 then we do nothing else we move the value to dptr */
9476 if (AOP_TYPE(left) != AOP_STR) {
9477 /* if this is remateriazable */
9478 if (AOP_TYPE(left) == AOP_IMMD)
9479 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9480 else { /* we need to get it byte by byte */
9481 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9482 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9483 if (options.model == MODEL_FLAT24)
9485 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9489 /* so dptr know contains the address */
9490 pic16_freeAsmop(left,NULL,ic,TRUE);
9491 pic16_aopOp(result,ic,FALSE);
9493 /* if bit then unpack */
9494 if (IS_BITFIELD(retype))
9495 genUnpackBits(result,"dptr",CPOINTER);
9497 size = AOP_SIZE(result);
9501 pic16_emitcode("clr","a");
9502 pic16_emitcode("movc","a,@a+dptr");
9503 pic16_aopPut(AOP(result),"a",offset++);
9505 pic16_emitcode("inc","dptr");
9509 pic16_freeAsmop(result,NULL,ic,TRUE);
9512 /*-----------------------------------------------------------------*/
9513 /* genGenPointerGet - gget value from generic pointer space */
9514 /*-----------------------------------------------------------------*/
9515 static void genGenPointerGet (operand *left,
9516 operand *result, iCode *ic)
9518 int size, offset, lit;
9519 sym_link *retype = getSpec(operandType(result));
9521 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9522 pic16_aopOp(left,ic,FALSE);
9523 pic16_aopOp(result,ic,FALSE);
9524 size = AOP_SIZE(result);
9526 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9528 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9530 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9531 // load FSR0 from immediate
9532 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9534 // pic16_loadFSR0( left );
9539 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9541 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9548 else { /* we need to get it byte by byte */
9549 // set up FSR0 with address from left
9550 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9551 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9557 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9559 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9566 /* if bit then unpack */
9567 if (IS_BITFIELD(retype))
9568 genUnpackBits(result,"BAD",GPOINTER);
9571 pic16_freeAsmop(left,NULL,ic,TRUE);
9572 pic16_freeAsmop(result,NULL,ic,TRUE);
9576 /*-----------------------------------------------------------------*/
9577 /* genConstPointerGet - get value from const generic pointer space */
9578 /*-----------------------------------------------------------------*/
9579 static void genConstPointerGet (operand *left,
9580 operand *result, iCode *ic)
9582 //sym_link *retype = getSpec(operandType(result));
9583 // symbol *albl = newiTempLabel(NULL); // patch 15
9584 // symbol *blbl = newiTempLabel(NULL); //
9585 // PIC_OPCODE poc; // patch 15
9589 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9590 pic16_aopOp(left,ic,FALSE);
9591 pic16_aopOp(result,ic,TRUE);
9592 size = AOP_SIZE(result);
9594 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9596 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9598 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9599 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9600 pic16_emitpLabel(albl->key);
9602 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9604 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9605 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9606 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9607 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9608 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9610 pic16_emitpLabel(blbl->key);
9612 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9616 // set up table pointer
9617 if( (AOP_TYPE(left) == AOP_PCODE)
9618 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9619 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
9621 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9622 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9623 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9624 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9625 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9626 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9630 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9631 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9632 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9638 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9639 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9643 pic16_freeAsmop(left,NULL,ic,TRUE);
9644 pic16_freeAsmop(result,NULL,ic,TRUE);
9647 /*-----------------------------------------------------------------*/
9648 /* genPointerGet - generate code for pointer get */
9649 /*-----------------------------------------------------------------*/
9650 static void genPointerGet (iCode *ic)
9652 operand *left, *result ;
9653 sym_link *type, *etype;
9656 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9659 result = IC_RESULT(ic) ;
9661 /* depending on the type of pointer we need to
9662 move it to the correct pointer register */
9663 type = operandType(left);
9664 etype = getSpec(type);
9667 if (IS_PTR_CONST(type))
9669 if (IS_CODEPTR(type))
9671 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9673 /* if left is of type of pointer then it is simple */
9674 if (IS_PTR(type) && !IS_FUNC(type->next))
9675 p_type = DCL_TYPE(type);
9677 /* we have to go by the storage class */
9678 p_type = PTR_TYPE(SPEC_OCLS(etype));
9680 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9682 if (SPEC_OCLS(etype)->codesp ) {
9683 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9684 //p_type = CPOINTER ;
9687 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9688 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9689 /*p_type = FPOINTER ;*/
9691 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9692 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9693 /* p_type = PPOINTER; */
9695 if (SPEC_OCLS(etype) == idata )
9696 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9697 /* p_type = IPOINTER; */
9699 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9700 /* p_type = POINTER ; */
9703 /* now that we have the pointer type we assign
9704 the pointer values */
9709 genNearPointerGet (left,result,ic);
9713 genPagedPointerGet(left,result,ic);
9717 genFarPointerGet (left,result,ic);
9721 genConstPointerGet (left,result,ic);
9722 //pic16_emitcodePointerGet (left,result,ic);
9727 if (IS_PTR_CONST(type))
9728 genConstPointerGet (left,result,ic);
9731 genGenPointerGet (left,result,ic);
9737 /*-----------------------------------------------------------------*/
9738 /* genPackBits - generates code for packed bit storage */
9739 /*-----------------------------------------------------------------*/
9740 static void genPackBits (sym_link *etype ,
9742 char *rname, int p_type)
9750 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9751 blen = SPEC_BLEN(etype);
9752 bstr = SPEC_BSTR(etype);
9754 if(AOP_TYPE(right) == AOP_LIT) {
9755 if((blen == 1) && (bstr < 8)) {
9757 /* it is a single bit, so use the appropriate bit instructions */
9759 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9761 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9762 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9764 pic16_emitpcode(POC_BSF,
9765 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9767 pic16_emitpcode(POC_BCF,
9768 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9774 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9777 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9779 /* if the bit lenth is less than or */
9780 /* it exactly fits a byte then */
9781 if((shCnt=SPEC_BSTR(etype))
9782 || SPEC_BLEN(etype) <= 8 ) {
9784 /* shift left acc */
9787 /* using PRODL as a temporary register here */
9788 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9794 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9795 // pic16_emitcode ("mov","b,a");
9796 // pic16_emitcode("mov","a,@%s",rname);
9800 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9801 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9802 (unsigned char)(0xff >> (8-bstr))) ));
9803 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9804 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9811 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9812 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9817 if ( SPEC_BLEN(etype) <= 8 )
9820 pic16_emitcode("inc","%s",rname);
9821 rLen = SPEC_BLEN(etype) ;
9825 /* now generate for lengths greater than one byte */
9828 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9838 pic16_emitcode("mov","@%s,a",rname);
9840 pic16_emitcode("mov","@%s,%s",rname,l);
9845 pic16_emitcode("movx","@dptr,a");
9850 DEBUGpic16_emitcode(";lcall","__gptrput");
9853 pic16_emitcode ("inc","%s",rname);
9858 /* last last was not complete */
9860 /* save the byte & read byte */
9863 pic16_emitcode ("mov","b,a");
9864 pic16_emitcode("mov","a,@%s",rname);
9868 pic16_emitcode ("mov","b,a");
9869 pic16_emitcode("movx","a,@dptr");
9873 pic16_emitcode ("push","b");
9874 pic16_emitcode ("push","acc");
9875 pic16_emitcode ("lcall","__gptrget");
9876 pic16_emitcode ("pop","b");
9880 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9881 pic16_emitcode ("orl","a,b");
9884 if (p_type == GPOINTER)
9885 pic16_emitcode("pop","b");
9890 pic16_emitcode("mov","@%s,a",rname);
9894 pic16_emitcode("movx","@dptr,a");
9898 DEBUGpic16_emitcode(";lcall","__gptrput");
9902 /*-----------------------------------------------------------------*/
9903 /* genDataPointerSet - remat pointer to data space */
9904 /*-----------------------------------------------------------------*/
9905 static void genDataPointerSet(operand *right,
9909 int size, offset = 0, resoffset=0 ;
9911 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9912 pic16_aopOp(right,ic,FALSE);
9914 size = AOP_SIZE(right);
9916 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9919 if ( AOP_TYPE(result) == AOP_PCODE) {
9920 fprintf(stderr,"genDataPointerSet %s, %d\n",
9921 AOP(result)->aopu.pcop->name,
9922 (AOP(result)->aopu.pcop->type == PO_DIR)?
9923 PCOR(AOP(result)->aopu.pcop)->instance:
9924 PCOI(AOP(result)->aopu.pcop)->offset);
9928 if(AOP(result)->aopu.pcop->type == PO_DIR)
9929 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9932 if (AOP_TYPE(right) == AOP_LIT) {
9933 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9935 lit = lit >> (8*offset);
9937 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9938 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9940 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9943 mov2w(AOP(right), offset);
9944 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9950 pic16_freeAsmop(right,NULL,ic,TRUE);
9955 /*-----------------------------------------------------------------*/
9956 /* genNearPointerSet - pic16_emitcode for near pointer put */
9957 /*-----------------------------------------------------------------*/
9958 static void genNearPointerSet (operand *right,
9965 sym_link *ptype = operandType(result);
9968 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9969 retype= getSpec(operandType(right));
9970 resetype = getSpec(operandType(result));
9972 pic16_aopOp(result,ic,FALSE);
9974 /* if the result is rematerializable &
9975 * in data space & not a bit variable */
9977 /* and result is not a bit variable */
9978 if (AOP_TYPE(result) == AOP_PCODE
9979 // && AOP_TYPE(result) == AOP_IMMD
9980 && DCL_TYPE(ptype) == POINTER
9981 && !IS_BITFIELD(retype)
9982 && !IS_BITFIELD(resetype)) {
9984 genDataPointerSet (right,result,ic);
9985 pic16_freeAsmop(result,NULL,ic,TRUE);
9989 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9990 pic16_aopOp(right,ic,FALSE);
9991 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9993 /* if the value is already in a pointer register
9994 * then don't need anything more */
9995 if (!AOP_INPREG(AOP(result))) {
9996 /* otherwise get a free pointer register */
9997 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9999 if( (AOP_TYPE(result) == AOP_PCODE)
10000 && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10001 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10003 pic16_loadFSR0( result ); // patch 10
10005 // set up FSR0 with address of result
10006 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10007 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10012 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10014 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10016 /* if bitfield then unpack the bits */
10017 if (IS_BITFIELD(resetype)) {
10018 genPackBits (resetype, right, NULL, POINTER);
10020 /* we have can just get the values */
10021 int size = AOP_SIZE(right);
10024 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10026 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10029 //pic16_emitcode("mov","@%s,a",rname);
10030 pic16_emitcode("movf","indf0,w ;1");
10033 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
10034 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
10036 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
10038 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
10040 } else { // no literal //
10042 pic16_emitpcode(POC_MOVFF, //
10043 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10044 pic16_popCopyReg(&pic16_pc_postinc0))); //
10046 pic16_emitpcode(POC_MOVFF, //
10047 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10048 pic16_popCopyReg(&pic16_pc_indf0))); //
10056 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10057 /* now some housekeeping stuff */
10059 /* we had to allocate for this iCode */
10060 pic16_freeAsmop(NULL,aop,ic,TRUE);
10062 /* we did not allocate which means left
10063 * already in a pointer register, then
10064 * if size > 0 && this could be used again
10065 * we have to point it back to where it
10067 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10068 if (AOP_SIZE(right) > 1
10069 && !OP_SYMBOL(result)->remat
10070 && ( OP_SYMBOL(result)->liveTo > ic->seq
10073 int size = AOP_SIZE(right) - 1;
10076 pic16_emitcode("decf","fsr0,f");
10077 //pic16_emitcode("dec","%s",rname);
10081 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10084 pic16_freeAsmop(right,NULL,ic,TRUE);
10085 pic16_freeAsmop(result,NULL,ic,TRUE);
10088 /*-----------------------------------------------------------------*/
10089 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
10090 /*-----------------------------------------------------------------*/
10091 static void genPagedPointerSet (operand *right,
10096 regs *preg = NULL ;
10100 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10102 retype= getSpec(operandType(right));
10104 pic16_aopOp(result,ic,FALSE);
10106 /* if the value is already in a pointer register
10107 then don't need anything more */
10108 if (!AOP_INPREG(AOP(result))) {
10109 /* otherwise get a free pointer register */
10111 preg = getFreePtr(ic,&aop,FALSE);
10112 pic16_emitcode("mov","%s,%s",
10114 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10115 rname = preg->name ;
10117 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10119 pic16_freeAsmop(result,NULL,ic,TRUE);
10120 pic16_aopOp (right,ic,FALSE);
10122 /* if bitfield then unpack the bits */
10123 if (IS_BITFIELD(retype))
10124 genPackBits (retype,right,rname,PPOINTER);
10126 /* we have can just get the values */
10127 int size = AOP_SIZE(right);
10131 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10134 pic16_emitcode("movx","@%s,a",rname);
10137 pic16_emitcode("inc","%s",rname);
10143 /* now some housekeeping stuff */
10145 /* we had to allocate for this iCode */
10146 pic16_freeAsmop(NULL,aop,ic,TRUE);
10148 /* we did not allocate which means left
10149 already in a pointer register, then
10150 if size > 0 && this could be used again
10151 we have to point it back to where it
10153 if (AOP_SIZE(right) > 1 &&
10154 !OP_SYMBOL(result)->remat &&
10155 ( OP_SYMBOL(result)->liveTo > ic->seq ||
10157 int size = AOP_SIZE(right) - 1;
10159 pic16_emitcode("dec","%s",rname);
10164 pic16_freeAsmop(right,NULL,ic,TRUE);
10169 /*-----------------------------------------------------------------*/
10170 /* genFarPointerSet - set value from far space */
10171 /*-----------------------------------------------------------------*/
10172 static void genFarPointerSet (operand *right,
10173 operand *result, iCode *ic)
10176 sym_link *retype = getSpec(operandType(right));
10178 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10179 pic16_aopOp(result,ic,FALSE);
10181 /* if the operand is already in dptr
10182 then we do nothing else we move the value to dptr */
10183 if (AOP_TYPE(result) != AOP_STR) {
10184 /* if this is remateriazable */
10185 if (AOP_TYPE(result) == AOP_IMMD)
10186 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10187 else { /* we need to get it byte by byte */
10188 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10189 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10190 if (options.model == MODEL_FLAT24)
10192 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10196 /* so dptr know contains the address */
10197 pic16_freeAsmop(result,NULL,ic,TRUE);
10198 pic16_aopOp(right,ic,FALSE);
10200 /* if bit then unpack */
10201 if (IS_BITFIELD(retype))
10202 genPackBits(retype,right,"dptr",FPOINTER);
10204 size = AOP_SIZE(right);
10208 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10210 pic16_emitcode("movx","@dptr,a");
10212 pic16_emitcode("inc","dptr");
10216 pic16_freeAsmop(right,NULL,ic,TRUE);
10219 /*-----------------------------------------------------------------*/
10220 /* genGenPointerSet - set value from generic pointer space */
10221 /*-----------------------------------------------------------------*/
10222 static void genGenPointerSet (operand *right,
10223 operand *result, iCode *ic)
10225 int i, size, offset, lit;
10226 sym_link *retype = getSpec(operandType(right));
10228 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10230 pic16_aopOp(result,ic,FALSE);
10231 pic16_aopOp(right,ic,FALSE);
10232 size = AOP_SIZE(right);
10235 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10237 /* if the operand is already in dptr
10238 then we do nothing else we move the value to dptr */
10239 if (AOP_TYPE(result) != AOP_STR) {
10240 /* if this is remateriazable */
10241 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10242 // WARNING: anythig until "else" is untested!
10243 if (AOP_TYPE(result) == AOP_IMMD) {
10244 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10245 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10246 // load FSR0 from immediate
10247 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10251 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10253 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10259 else { /* we need to get it byte by byte */
10260 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10261 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10263 // set up FSR0 with address of result
10264 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10265 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10267 /* hack hack! see if this the FSR. If so don't load W */
10268 if(AOP_TYPE(right) != AOP_ACC) {
10270 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10272 if(AOP_TYPE(right) == AOP_LIT)
10275 // note: pic16_popGet handles sign extension
10276 for(i=0;i<size;i++) {
10277 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10279 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10281 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10286 for(i=0;i<size;i++) {
10288 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10289 pic16_popCopyReg(&pic16_pc_postinc0)));
10291 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10292 pic16_popCopyReg(&pic16_pc_indf0)));
10298 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10299 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10301 } // if (AOP_TYPE(result) != AOP_IMMD)
10303 } // if (AOP_TYPE(result) != AOP_STR)
10304 /* so dptr know contains the address */
10307 /* if bit then unpack */
10308 if (IS_BITFIELD(retype))
10309 genPackBits(retype,right,"dptr",GPOINTER);
10311 size = AOP_SIZE(right);
10314 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
10316 // set up FSR0 with address of result
10317 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10318 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10321 if (AOP_TYPE(right) == AOP_LIT) {
10322 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10324 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10326 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10328 } else { // no literal
10330 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10332 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10340 pic16_freeAsmop(right,NULL,ic,TRUE);
10341 pic16_freeAsmop(result,NULL,ic,TRUE);
10344 /*-----------------------------------------------------------------*/
10345 /* genPointerSet - stores the value into a pointer location */
10346 /*-----------------------------------------------------------------*/
10347 static void genPointerSet (iCode *ic)
10349 operand *right, *result ;
10350 sym_link *type, *etype;
10353 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10355 right = IC_RIGHT(ic);
10356 result = IC_RESULT(ic) ;
10358 /* depending on the type of pointer we need to
10359 move it to the correct pointer register */
10360 type = operandType(result);
10361 etype = getSpec(type);
10362 /* if left is of type of pointer then it is simple */
10363 if (IS_PTR(type) && !IS_FUNC(type->next)) {
10364 p_type = DCL_TYPE(type);
10367 /* we have to go by the storage class */
10368 p_type = PTR_TYPE(SPEC_OCLS(etype));
10370 /* if (SPEC_OCLS(etype)->codesp ) { */
10371 /* p_type = CPOINTER ; */
10374 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10375 /* p_type = FPOINTER ; */
10377 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10378 /* p_type = PPOINTER ; */
10380 /* if (SPEC_OCLS(etype) == idata ) */
10381 /* p_type = IPOINTER ; */
10383 /* p_type = POINTER ; */
10386 /* now that we have the pointer type we assign
10387 the pointer values */
10392 genNearPointerSet (right,result,ic);
10396 genPagedPointerSet (right,result,ic);
10400 genFarPointerSet (right,result,ic);
10404 genGenPointerSet (right,result,ic);
10408 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10409 "genPointerSet: illegal pointer type");
10413 /*-----------------------------------------------------------------*/
10414 /* genIfx - generate code for Ifx statement */
10415 /*-----------------------------------------------------------------*/
10416 static void genIfx (iCode *ic, iCode *popIc)
10418 operand *cond = IC_COND(ic);
10421 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10423 pic16_aopOp(cond,ic,FALSE);
10425 /* get the value into acc */
10426 if (AOP_TYPE(cond) != AOP_CRY)
10427 pic16_toBoolean(cond);
10430 /* the result is now in the accumulator */
10431 pic16_freeAsmop(cond,NULL,ic,TRUE);
10433 /* if there was something to be popped then do it */
10437 /* if the condition is a bit variable */
10438 if (isbit && IS_ITEMP(cond) &&
10440 genIfxJump(ic,SPIL_LOC(cond)->rname);
10441 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10444 if (isbit && !IS_ITEMP(cond))
10445 genIfxJump(ic,OP_SYMBOL(cond)->rname);
10447 genIfxJump(ic,"a");
10453 /*-----------------------------------------------------------------*/
10454 /* genAddrOf - generates code for address of */
10455 /*-----------------------------------------------------------------*/
10456 static void genAddrOf (iCode *ic)
10458 operand *result, *left;
10460 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
10461 pCodeOp *pcop0, *pcop1, *pcop2;
10463 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10465 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10466 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10468 sym = OP_SYMBOL( left );
10470 size = AOP_SIZE(IC_RESULT(ic));
10472 // if(pic16_debug_verbose) {
10473 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10474 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10477 /* Assume that what we want the address of is in data space
10478 * since there is no stack on the PIC, yet! -- VR */
10480 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10483 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10486 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10490 pic16_emitpcode(POC_MOVLW, pcop0);
10491 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10492 pic16_emitpcode(POC_MOVLW, pcop1);
10493 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10494 pic16_emitpcode(POC_MOVLW, pcop2);
10495 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10498 pic16_emitpcode(POC_MOVLW, pcop0);
10499 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10500 pic16_emitpcode(POC_MOVLW, pcop1);
10501 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10503 pic16_emitpcode(POC_MOVLW, pcop0);
10504 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10507 pic16_freeAsmop(result,NULL,ic,TRUE);
10508 pic16_freeAsmop(left, NULL, ic, FALSE);
10513 /*-----------------------------------------------------------------*/
10514 /* genFarFarAssign - assignment when both are in far space */
10515 /*-----------------------------------------------------------------*/
10516 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10518 int size = AOP_SIZE(right);
10521 /* first push the right side on to the stack */
10523 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10525 pic16_emitcode ("push","acc");
10528 pic16_freeAsmop(right,NULL,ic,FALSE);
10529 /* now assign DPTR to result */
10530 pic16_aopOp(result,ic,FALSE);
10531 size = AOP_SIZE(result);
10533 pic16_emitcode ("pop","acc");
10534 pic16_aopPut(AOP(result),"a",--offset);
10536 pic16_freeAsmop(result,NULL,ic,FALSE);
10541 /*-----------------------------------------------------------------*/
10542 /* genAssign - generate code for assignment */
10543 /*-----------------------------------------------------------------*/
10544 static void genAssign (iCode *ic)
10546 operand *result, *right;
10547 int size, offset,know_W;
10548 unsigned long lit = 0L;
10550 result = IC_RESULT(ic);
10551 right = IC_RIGHT(ic) ;
10553 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10555 /* if they are the same */
10556 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10559 pic16_aopOp(right,ic,FALSE);
10560 pic16_aopOp(result,ic,TRUE);
10562 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10564 /* if they are the same registers */
10565 if (pic16_sameRegs(AOP(right),AOP(result)))
10568 /* if the result is a bit */
10569 if (AOP_TYPE(result) == AOP_CRY) {
10570 /* if the right size is a literal then
10571 we know what the value is */
10572 if (AOP_TYPE(right) == AOP_LIT) {
10574 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10575 pic16_popGet(AOP(result),0));
10577 if (((int) operandLitValue(right)))
10578 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10579 AOP(result)->aopu.aop_dir,
10580 AOP(result)->aopu.aop_dir);
10582 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10583 AOP(result)->aopu.aop_dir,
10584 AOP(result)->aopu.aop_dir);
10588 /* the right is also a bit variable */
10589 if (AOP_TYPE(right) == AOP_CRY) {
10590 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10591 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10592 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10594 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10595 AOP(result)->aopu.aop_dir,
10596 AOP(result)->aopu.aop_dir);
10597 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10598 AOP(right)->aopu.aop_dir,
10599 AOP(right)->aopu.aop_dir);
10600 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10601 AOP(result)->aopu.aop_dir,
10602 AOP(result)->aopu.aop_dir);
10606 /* we need to or */
10607 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10608 pic16_toBoolean(right);
10610 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10611 //pic16_aopPut(AOP(result),"a",0);
10615 /* bit variables done */
10617 size = AOP_SIZE(result);
10620 if(AOP_TYPE(right) == AOP_LIT) {
10621 if(!IS_FLOAT(operandType( right )))
10622 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10625 unsigned long lit_int;
10629 /* take care if literal is a float */
10630 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10631 lit = info.lit_int;
10635 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10636 // sizeof(unsigned long int), sizeof(float));
10638 if(AOP_TYPE(right) != AOP_LIT
10639 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10640 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10642 // set up table pointer
10643 if( (AOP_TYPE(right) == AOP_PCODE)
10644 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10645 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10647 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10648 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10649 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10650 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10651 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10652 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10654 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10655 pic16_popCopyReg(&pic16_pc_tblptrl)));
10656 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10657 pic16_popCopyReg(&pic16_pc_tblptrh)));
10658 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10659 pic16_popCopyReg(&pic16_pc_tblptru)));
10662 size = min(AOP_SIZE(right), AOP_SIZE(result));
10664 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10665 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10666 pic16_popGet(AOP(result),offset)));
10670 if(AOP_SIZE(result) > AOP_SIZE(right)) {
10671 size = AOP_SIZE(result) - AOP_SIZE(right);
10673 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10682 /* VR - What is this?! */
10683 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10684 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10685 if(aopIdx(AOP(result),0) == 4) {
10686 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10688 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10689 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10693 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10698 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10699 if(AOP_TYPE(right) == AOP_LIT) {
10701 if(know_W != (lit&0xff))
10702 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10704 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10706 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10710 } else if (AOP_TYPE(right) == AOP_CRY) {
10711 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10713 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10714 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10716 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10717 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10718 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10720 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10723 /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10724 normally should work, but mind that the W register live range
10725 is not checked, so if the code generator assumes that the W
10726 is already loaded after such a pair, wrong code will be generated.
10728 Checking the live range is the next step.
10729 This is experimental code yet and has not been fully tested yet.
10730 USE WITH CARE. Revert to old code by setting 0 to the condition above.
10731 Vangelis Rokas 030603 (vrokas@otenet.gr) */
10733 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10735 /* This is the old code, which is assumed(?!) that works fine(!?) */
10737 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10738 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10747 pic16_freeAsmop (right,NULL,ic,FALSE);
10748 pic16_freeAsmop (result,NULL,ic,TRUE);
10751 /*-----------------------------------------------------------------*/
10752 /* genJumpTab - generates code for jump table */
10753 /*-----------------------------------------------------------------*/
10754 static void genJumpTab (iCode *ic)
10759 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10761 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10762 /* get the condition into accumulator */
10763 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10765 /* multiply by three */
10766 pic16_emitcode("add","a,acc");
10767 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10769 jtab = newiTempLabel(NULL);
10770 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10771 pic16_emitcode("jmp","@a+dptr");
10772 pic16_emitcode("","%05d_DS_:",jtab->key+100);
10774 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10775 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10777 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10778 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10779 pic16_emitpLabel(jtab->key);
10781 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10783 /* now generate the jump labels */
10784 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10785 jtab = setNextItem(IC_JTLABELS(ic))) {
10786 pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10787 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10793 /*-----------------------------------------------------------------*/
10794 /* genMixedOperation - gen code for operators between mixed types */
10795 /*-----------------------------------------------------------------*/
10797 TSD - Written for the PIC port - but this unfortunately is buggy.
10798 This routine is good in that it is able to efficiently promote
10799 types to different (larger) sizes. Unfortunately, the temporary
10800 variables that are optimized out by this routine are sometimes
10801 used in other places. So until I know how to really parse the
10802 iCode tree, I'm going to not be using this routine :(.
10804 static int genMixedOperation (iCode *ic)
10807 operand *result = IC_RESULT(ic);
10808 sym_link *ctype = operandType(IC_LEFT(ic));
10809 operand *right = IC_RIGHT(ic);
10815 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10817 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10823 nextright = IC_RIGHT(nextic);
10824 nextleft = IC_LEFT(nextic);
10825 nextresult = IC_RESULT(nextic);
10827 pic16_aopOp(right,ic,FALSE);
10828 pic16_aopOp(result,ic,FALSE);
10829 pic16_aopOp(nextright, nextic, FALSE);
10830 pic16_aopOp(nextleft, nextic, FALSE);
10831 pic16_aopOp(nextresult, nextic, FALSE);
10833 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10835 operand *t = right;
10839 pic16_emitcode(";remove right +","");
10841 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10843 operand *t = right;
10847 pic16_emitcode(";remove left +","");
10851 big = AOP_SIZE(nextleft);
10852 small = AOP_SIZE(nextright);
10854 switch(nextic->op) {
10857 pic16_emitcode(";optimize a +","");
10858 /* if unsigned or not an integral type */
10859 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10860 pic16_emitcode(";add a bit to something","");
10863 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10865 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10866 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10867 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10869 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10877 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10878 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10879 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10882 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10884 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10885 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10886 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10887 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10888 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10891 pic16_emitcode("rlf","known_zero,w");
10898 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10899 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10900 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10902 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10912 pic16_freeAsmop(right,NULL,ic,TRUE);
10913 pic16_freeAsmop(result,NULL,ic,TRUE);
10914 pic16_freeAsmop(nextright,NULL,ic,TRUE);
10915 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10917 nextic->generated = 1;
10924 /*-----------------------------------------------------------------*/
10925 /* genCast - gen code for casting */
10926 /*-----------------------------------------------------------------*/
10927 static void genCast (iCode *ic)
10929 operand *result = IC_RESULT(ic);
10930 sym_link *ctype = operandType(IC_LEFT(ic));
10931 sym_link *rtype = operandType(IC_RIGHT(ic));
10932 operand *right = IC_RIGHT(ic);
10935 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10936 /* if they are equivalent then do nothing */
10937 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10940 pic16_aopOp(right,ic,FALSE) ;
10941 pic16_aopOp(result,ic,FALSE);
10943 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10945 /* if the result is a bit */
10946 if (AOP_TYPE(result) == AOP_CRY) {
10948 /* if the right size is a literal then
10949 * we know what the value is */
10950 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10952 if (AOP_TYPE(right) == AOP_LIT) {
10953 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10954 pic16_popGet(AOP(result),0));
10956 if (((int) operandLitValue(right)))
10957 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10958 AOP(result)->aopu.aop_dir,
10959 AOP(result)->aopu.aop_dir);
10961 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10962 AOP(result)->aopu.aop_dir,
10963 AOP(result)->aopu.aop_dir);
10967 /* the right is also a bit variable */
10968 if (AOP_TYPE(right) == AOP_CRY) {
10970 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10972 pic16_emitcode("clrc","");
10973 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10974 AOP(right)->aopu.aop_dir,
10975 AOP(right)->aopu.aop_dir);
10976 pic16_aopPut(AOP(result),"c",0);
10980 /* we need to or */
10981 if (AOP_TYPE(right) == AOP_REG) {
10982 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10983 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10984 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10986 pic16_toBoolean(right);
10987 pic16_aopPut(AOP(result),"a",0);
10991 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10994 size = AOP_SIZE(result);
10996 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10998 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
10999 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11000 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
11003 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11008 /* if they are the same size : or less */
11009 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11011 /* if they are in the same place */
11012 if (pic16_sameRegs(AOP(right),AOP(result)))
11015 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11017 if (IS_PTR_CONST(rtype))
11019 if (IS_CODEPTR(rtype))
11021 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11024 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11026 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11028 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11031 if(AOP_TYPE(right) == AOP_IMMD) {
11032 pCodeOp *pcop0, *pcop1, *pcop2;
11033 symbol *sym = OP_SYMBOL( right );
11035 size = AOP_SIZE(result);
11037 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11039 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11041 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11044 pic16_emitpcode(POC_MOVLW, pcop0);
11045 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11046 pic16_emitpcode(POC_MOVLW, pcop1);
11047 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11048 pic16_emitpcode(POC_MOVLW, pcop2);
11049 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11052 pic16_emitpcode(POC_MOVLW, pcop0);
11053 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11054 pic16_emitpcode(POC_MOVLW, pcop1);
11055 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11057 pic16_emitpcode(POC_MOVLW, pcop0);
11058 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11062 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11063 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11064 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11065 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11066 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11067 if(AOP_SIZE(result) <2)
11068 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11070 /* if they in different places then copy */
11071 size = AOP_SIZE(result);
11074 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11075 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11082 /* if the result is of type pointer */
11083 if (IS_PTR(ctype)) {
11085 sym_link *type = operandType(right);
11086 sym_link *etype = getSpec(type);
11088 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
11090 /* pointer to generic pointer */
11091 if (IS_GENPTR(ctype)) {
11095 p_type = DCL_TYPE(type);
11097 /* we have to go by the storage class */
11098 p_type = PTR_TYPE(SPEC_OCLS(etype));
11100 /* if (SPEC_OCLS(etype)->codesp ) */
11101 /* p_type = CPOINTER ; */
11103 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11104 /* p_type = FPOINTER ; */
11106 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11107 /* p_type = PPOINTER; */
11109 /* if (SPEC_OCLS(etype) == idata ) */
11110 /* p_type = IPOINTER ; */
11112 /* p_type = POINTER ; */
11115 /* the first two bytes are known */
11116 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
11117 size = GPTRSIZE - 1;
11120 if(offset < AOP_SIZE(right)) {
11121 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
11122 if ((AOP_TYPE(right) == AOP_PCODE) &&
11123 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11124 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11125 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11127 pic16_aopPut(AOP(result),
11128 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11132 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11135 /* the last byte depending on type */
11139 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11142 pic16_emitcode(";BUG!? ","%d",__LINE__);
11146 pic16_emitcode(";BUG!? ","%d",__LINE__);
11150 pic16_emitcode(";BUG!? ","%d",__LINE__);
11155 /* this should never happen */
11156 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11157 "got unknown pointer type");
11160 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
11164 /* just copy the pointers */
11165 size = AOP_SIZE(result);
11168 pic16_aopPut(AOP(result),
11169 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11178 /* so we now know that the size of destination is greater
11179 than the size of the source.
11180 Now, if the next iCode is an operator then we might be
11181 able to optimize the operation without performing a cast.
11183 if(genMixedOperation(ic))
11186 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11188 /* we move to result for the size of source */
11189 size = AOP_SIZE(right);
11192 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11193 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11197 /* now depending on the sign of the destination */
11198 size = AOP_SIZE(result) - AOP_SIZE(right);
11199 /* if unsigned or not an integral type */
11200 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11202 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11204 /* we need to extend the sign :( */
11207 /* Save one instruction of casting char to int */
11208 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11209 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11210 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
11212 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11215 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11217 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
11219 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
11222 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
11227 pic16_freeAsmop(right,NULL,ic,TRUE);
11228 pic16_freeAsmop(result,NULL,ic,TRUE);
11232 /*-----------------------------------------------------------------*/
11233 /* genDjnz - generate decrement & jump if not zero instrucion */
11234 /*-----------------------------------------------------------------*/
11235 static int genDjnz (iCode *ic, iCode *ifx)
11237 symbol *lbl, *lbl1;
11238 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11243 /* if the if condition has a false label
11244 then we cannot save */
11248 /* if the minus is not of the form
11250 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11251 !IS_OP_LITERAL(IC_RIGHT(ic)))
11254 if (operandLitValue(IC_RIGHT(ic)) != 1)
11257 /* if the size of this greater than one then no
11259 if (getSize(operandType(IC_RESULT(ic))) > 1)
11262 /* otherwise we can save BIG */
11263 lbl = newiTempLabel(NULL);
11264 lbl1= newiTempLabel(NULL);
11266 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11268 if (IS_AOP_PREG(IC_RESULT(ic))) {
11269 pic16_emitcode("dec","%s",
11270 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11271 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11272 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11276 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11277 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11279 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11280 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
11283 /* pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11284 /* pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11285 /* pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11286 /* pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11289 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11290 ifx->generated = 1;
11294 /*-----------------------------------------------------------------*/
11295 /* genReceive - generate code for a receive iCode */
11296 /*-----------------------------------------------------------------*/
11297 static void genReceive (iCode *ic)
11299 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11301 if (isOperandInFarSpace(IC_RESULT(ic)) &&
11302 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11303 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11305 int size = getSize(operandType(IC_RESULT(ic)));
11306 int offset = pic16_fReturnSizePic - size;
11309 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11310 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11314 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
11316 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11317 size = AOP_SIZE(IC_RESULT(ic));
11320 pic16_emitcode ("pop","acc");
11321 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11324 DEBUGpic16_emitcode ("; ***","2 %s %d",__FUNCTION__,__LINE__);
11327 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11329 assignResultValue(IC_RESULT(ic), 0);
11332 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11335 /*-----------------------------------------------------------------*/
11336 /* genDummyRead - generate code for dummy read of volatiles */
11337 /*-----------------------------------------------------------------*/
11339 genDummyRead (iCode * ic)
11341 pic16_emitcode ("; genDummyRead","");
11342 pic16_emitcode ("; not implemented","");
11347 /*-----------------------------------------------------------------*/
11348 /* genpic16Code - generate code for pic16 based controllers */
11349 /*-----------------------------------------------------------------*/
11351 * At this point, ralloc.c has gone through the iCode and attempted
11352 * to optimize in a way suitable for a PIC. Now we've got to generate
11353 * PIC instructions that correspond to the iCode.
11355 * Once the instructions are generated, we'll pass through both the
11356 * peep hole optimizer and the pCode optimizer.
11357 *-----------------------------------------------------------------*/
11359 void genpic16Code (iCode *lic)
11364 lineHead = lineCurr = NULL;
11366 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11367 pic16_addpBlock(pb);
11370 /* if debug information required */
11371 if (options.debug && currFunc) {
11373 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11378 for (ic = lic ; ic ; ic = ic->next ) {
11380 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11381 if ( cln != ic->lineno ) {
11382 if ( options.debug ) {
11383 debugFile->writeCLine (ic);
11386 if(!options.noCcodeInAsm) {
11387 pic16_addpCode2pBlock(pb,
11388 pic16_newpCodeCSource(ic->lineno, ic->filename,
11389 printCLine(ic->filename, ic->lineno)));
11395 if(options.iCodeInAsm) {
11397 /* insert here code to print iCode as comment */
11398 l = Safe_strdup(printILine(ic));
11399 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11402 /* if the result is marked as
11403 spilt and rematerializable or code for
11404 this has already been generated then
11406 if (resultRemat(ic) || ic->generated )
11409 /* depending on the operation */
11428 /* IPOP happens only when trying to restore a
11429 spilt live range, if there is an ifx statement
11430 following this pop then the if statement might
11431 be using some of the registers being popped which
11432 would destroy the contents of the register so
11433 we need to check for this condition and handle it */
11435 ic->next->op == IFX &&
11436 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
11437 genIfx (ic->next,ic);
11455 genEndFunction (ic);
11471 pic16_genPlus (ic) ;
11475 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11476 pic16_genMinus (ic);
11492 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
11496 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11503 /* note these two are xlated by algebraic equivalence
11504 during parsing SDCC.y */
11505 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11506 "got '>=' or '<=' shouldn't have come here");
11510 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11522 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11526 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11530 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11554 genRightShift (ic);
11557 case GET_VALUE_AT_ADDRESS:
11562 if (POINTER_SET(ic))
11589 addSet(&_G.sendSet,ic);
11592 case DUMMY_READ_VOLATILE:
11602 /* now we are ready to call the
11603 peep hole optimizer */
11604 if (!options.nopeep) {
11605 peepHole (&lineHead);
11607 /* now do the actual printing */
11608 printLine (lineHead,codeOutFile);
11611 DFPRINTF((stderr,"printing pBlock\n\n"));
11612 pic16_printpBlock(stdout,pb);