1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic16
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002)
9 - Vangelis Rokas vrokas@otenet.gr (2003)
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 In other words, you are welcome to use, share and improve this program.
26 You are forbidden to forbid anyone else to use, share and improve
27 what you give them. Help stamp out software-hoarding!
30 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
31 Made everything static
32 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
50 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 void pic16_genMult8X8_8 (operand *, operand *,operand *);
53 void pic16_genMult16X16_16(operand *, operand *, operand *);
54 void pic16_genMult32X32_32(operand *, operand *, operand *);
55 pCode *pic16_AssembleLine(char *line, int peeps);
56 extern void pic16_printpBlock(FILE *of, pBlock *pb);
57 static asmop *newAsmop (short type);
58 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
59 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
60 static void mov2w (asmop *aop, int offset);
61 static int aopIdx (asmop *aop, int offset);
63 int pic16_labelOffset=0;
64 extern int pic16_debug_verbose;
65 static int optimized_for_speed = 0;
71 /* max_key keeps track of the largest label number used in
72 a function. This is then used to adjust the label offset
73 for the next function.
76 static int GpsuedoStkPtr=0;
78 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
79 unsigned int pic16aopLiteral (value *val, int offset);
80 const char *pic16_AopType(short type);
81 static iCode *ifxForOp ( operand *op, iCode *ic );
83 void pic16_pushpCodeOp(pCodeOp *pcop);
84 void pic16_poppCodeOp(pCodeOp *pcop);
86 static bool is_LitOp(operand *op);
87 static bool is_LitAOp(asmop *aop);
90 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
92 /* this is the down and dirty file with all kinds of
93 kludgy & hacky stuff. This is what it is all about
94 CODE GENERATION for a specific MCU . some of the
95 routines may be reusable, will have to see */
97 static char *zero = "#0x00";
98 static char *one = "#0x01";
99 static char *spname = "sp";
103 * Function return value policy (MSB-->LSB):
105 * 16 bits -> PRODL:WREG
106 * 24 bits -> PRODH:PRODL:WREG
107 * 32 bits -> FSR0L:PRODH:PRODL:WREG
108 * >32 bits -> on stack, and FSR0 points to the beginning
113 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
114 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
115 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
116 static char **fReturn = fReturnpic16;
118 static char *accUse[] = {"WREG"};
120 //static short rbank = -1;
133 /* Resolved ifx structure. This structure stores information
134 about an iCode ifx that makes it easier to generate code.
136 typedef struct resolvedIfx {
137 symbol *lbl; /* pointer to a label */
138 int condition; /* true or false ifx */
139 int generated; /* set true when the code associated with the ifx
143 extern int pic16_ptrRegReq ;
144 extern int pic16_nRegs;
145 extern FILE *codeOutFile;
146 static void saverbank (int, iCode *,bool);
148 static lineNode *lineHead = NULL;
149 static lineNode *lineCurr = NULL;
151 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
152 0xE0, 0xC0, 0x80, 0x00};
153 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
154 0x07, 0x03, 0x01, 0x00};
158 /*-----------------------------------------------------------------*/
159 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
160 /* exponent of 2 is returned, otherwise -1 is */
162 /* note that this is similar to the function `powof2' in SDCCsymt */
166 /*-----------------------------------------------------------------*/
167 static int my_powof2 (unsigned long num)
170 if( (num & (num-1)) == 0) {
183 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
185 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
187 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
188 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
189 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
190 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
191 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
192 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
193 ((result) ? AOP_SIZE(result) : 0));
196 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
199 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
201 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
202 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
203 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
204 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
205 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
206 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
210 void pic16_emitpcomment (char *fmt, ...)
213 char lb[INITIAL_INLINEASM];
219 vsprintf(lb+1,fmt,ap);
221 while (isspace(*lbp)) lbp++;
224 lineCurr = (lineCurr ?
225 connectLine(lineCurr,newLineNode(lb)) :
226 (lineHead = newLineNode(lb)));
227 lineCurr->isInline = _G.inLine;
228 lineCurr->isDebug = _G.debugLine;
230 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
233 // fprintf(stderr, "%s\n", lb);
236 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
239 char lb[INITIAL_INLINEASM];
242 if(!pic16_debug_verbose)
249 sprintf(lb,"%s\t",inst);
251 sprintf(lb,"%s",inst);
252 vsprintf(lb+(strlen(lb)),fmt,ap);
256 while (isspace(*lbp)) lbp++;
259 lineCurr = (lineCurr ?
260 connectLine(lineCurr,newLineNode(lb)) :
261 (lineHead = newLineNode(lb)));
262 lineCurr->isInline = _G.inLine;
263 lineCurr->isDebug = _G.debugLine;
265 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
268 // fprintf(stderr, "%s\n", lb);
271 void pic16_emitpLabel(int key)
273 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
276 void pic16_emitpLabelFORCE(int key)
278 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
281 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
285 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
287 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
289 // fprintf(stderr, "%s\n", pcop->name);
292 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
295 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
301 #define pic16_emitcode DEBUGpic16_emitcode
303 /*-----------------------------------------------------------------*/
304 /* pic16_emitcode - writes the code into a file : for now it is simple */
305 /*-----------------------------------------------------------------*/
306 void pic16_emitcode (char *inst,char *fmt, ...)
309 char lb[INITIAL_INLINEASM];
316 sprintf(lb,"%s\t",inst);
318 sprintf(lb,"%s",inst);
319 vsprintf(lb+(strlen(lb)),fmt,ap);
323 while (isspace(*lbp)) lbp++;
326 lineCurr = (lineCurr ?
327 connectLine(lineCurr,newLineNode(lb)) :
328 (lineHead = newLineNode(lb)));
329 lineCurr->isInline = _G.inLine;
330 lineCurr->isDebug = _G.debugLine;
332 // VR fprintf(stderr, "lb = <%s>\n", lbp);
334 // if(pic16_debug_verbose)
335 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
342 /*-----------------------------------------------------------------*/
343 /* pic16_emitDebuggerSymbol - associate the current code location */
344 /* with a debugger symbol */
345 /*-----------------------------------------------------------------*/
347 pic16_emitDebuggerSymbol (char * debugSym)
350 pic16_emitcode (";", "%s ==.", debugSym);
355 /*-----------------------------------------------------------------*/
356 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
357 /*-----------------------------------------------------------------*/
358 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
360 bool r0iu = FALSE , r1iu = FALSE;
361 bool r0ou = FALSE , r1ou = FALSE;
363 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
365 (*aopp)->type = AOP_STK;
367 /* the logic: if r0 & r1 used in the instruction
368 then we are in trouble otherwise */
370 /* first check if r0 & r1 are used by this
371 instruction, in which case we are in trouble */
372 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
373 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
378 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
379 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
381 /* if no usage of r0 then return it */
382 if (!r0iu && !r0ou) {
383 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
384 (*aopp)->type = AOP_R0;
386 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
389 /* if no usage of r1 then return it */
390 if (!r1iu && !r1ou) {
391 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
392 (*aopp)->type = AOP_R1;
394 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
397 /* now we know they both have usage */
398 /* if r0 not used in this instruction */
400 /* push it if not already pushed */
402 //pic16_emitcode ("push","%s",
403 // pic16_regWithIdx(R0_IDX)->dname);
407 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
408 (*aopp)->type = AOP_R0;
410 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
413 /* if r1 not used then */
416 /* push it if not already pushed */
418 //pic16_emitcode ("push","%s",
419 // pic16_regWithIdx(R1_IDX)->dname);
423 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
424 (*aopp)->type = AOP_R1;
425 return pic16_regWithIdx(R1_IDX);
429 /* I said end of world but not quite end of world yet */
430 /* if this is a result then we can push it on the stack*/
432 (*aopp)->type = AOP_STK;
436 /* other wise this is true end of the world */
437 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
438 "getFreePtr should never reach here");
442 /*-----------------------------------------------------------------*/
443 /* newAsmop - creates a new asmOp */
444 /*-----------------------------------------------------------------*/
445 static asmop *newAsmop (short type)
449 aop = Safe_calloc(1,sizeof(asmop));
454 static void genSetDPTR(int n)
458 pic16_emitcode(";", "Select standard DPTR");
459 pic16_emitcode("mov", "dps, #0x00");
463 pic16_emitcode(";", "Select alternate DPTR");
464 pic16_emitcode("mov", "dps, #0x01");
468 /*-----------------------------------------------------------------*/
469 /* resolveIfx - converts an iCode ifx into a form more useful for */
470 /* generating code */
471 /*-----------------------------------------------------------------*/
472 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
475 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
481 resIfx->condition = 1; /* assume that the ifx is true */
482 resIfx->generated = 0; /* indicate that the ifx has not been used */
485 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
488 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
489 __FUNCTION__,__LINE__,resIfx->lbl->key);
494 resIfx->lbl = IC_TRUE(ifx);
496 resIfx->lbl = IC_FALSE(ifx);
497 resIfx->condition = 0;
502 DEBUGpic16_emitcode("; ***","ifx true is non-null");
504 DEBUGpic16_emitcode("; ***","ifx false is non-null");
508 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
512 /*-----------------------------------------------------------------*/
513 /* pointerCode - returns the code for a pointer type */
514 /*-----------------------------------------------------------------*/
515 static int pointerCode (sym_link *etype)
518 return PTR_TYPE(SPEC_OCLS(etype));
523 /*-----------------------------------------------------------------*/
524 /* aopForSym - for a true symbol */
525 /*-----------------------------------------------------------------*/
526 static asmop *aopForSym (iCode *ic, operand *op, bool result)
528 symbol *sym=OP_SYMBOL(op);
530 memmap *space= SPEC_OCLS(sym->etype);
532 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
534 // sym = OP_SYMBOL(op);
536 /* if already has one */
538 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
542 /* if symbol was initially placed onStack then we must re-place it
543 * to direct memory, since pic16 does not have a specific stack */
545 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
548 SPEC_OCLS( sym->etype ) = data;
555 /* assign depending on the storage class */
556 /* if it is on the stack or indirectly addressable */
557 /* space we need to assign either r0 or r1 to it */
558 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
560 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
561 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
563 // sym->aop = aop = newAsmop(0);
564 // aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
565 // aop->size = getSize(sym->type);
567 fprintf(stderr, "%s:%d\t%s\n", __FILE__, __LINE__, __FUNCTION__);
569 sym->aop = aop = newAsmop (AOP_REG);
570 // aop->aopu.aop_dir = sym->name; //sym->rname ;
571 aop->aopu.aop_reg[0] = pic16_regWithIdx(IDX_PLUSW2); //pic16_pc_plusw2.r;
572 aop->size = getSize(sym->type);
573 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
575 /* initialise for stack access via frame pointer */
576 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
579 // if(IC_LEFT(ic))pic16_allocDirReg( IC_LEFT(ic) );
580 // else if(IC_RIGHT(ic))pic16_allocDirReg(IC_RIGHT(ic));
584 /* now assign the address of the variable to
585 the pointer register */
586 if (aop->type != AOP_STK) {
590 pic16_emitcode("push","acc");
592 pic16_emitcode("mov","a,_bp");
593 pic16_emitcode("add","a,#0x%02x",
595 ((char)(sym->stack - _G.nRegsSaved )) :
596 ((char)sym->stack)) & 0xff);
597 pic16_emitcode("mov","%s,a",
598 aop->aopu.aop_ptr->name);
601 pic16_emitcode("pop","acc");
603 pic16_emitcode("mov","%s,#%s",
604 aop->aopu.aop_ptr->name,
606 aop->paged = space->paged;
608 aop->aopu.aop_stk = sym->stack;
614 if (sym->onStack && options.stack10bit)
616 /* It's on the 10 bit stack, which is located in
620 //DEBUGpic16_emitcode(";","%d",__LINE__);
623 pic16_emitcode("push","acc");
625 pic16_emitcode("mov","a,_bp");
626 pic16_emitcode("add","a,#0x%02x",
628 ((char)(sym->stack - _G.nRegsSaved )) :
629 ((char)sym->stack)) & 0xff);
632 pic16_emitcode ("mov","dpx1,#0x40");
633 pic16_emitcode ("mov","dph1,#0x00");
634 pic16_emitcode ("mov","dpl1, a");
638 pic16_emitcode("pop","acc");
640 sym->aop = aop = newAsmop(AOP_DPTR2);
641 aop->size = getSize(sym->type);
645 //DEBUGpic16_emitcode(";","%d",__LINE__);
646 /* if in bit space */
647 if (IN_BITSPACE(space)) {
648 sym->aop = aop = newAsmop (AOP_CRY);
649 aop->aopu.aop_dir = sym->rname ;
650 aop->size = getSize(sym->type);
651 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
654 /* if it is in direct space */
655 if (IN_DIRSPACE(space)) {
656 sym->aop = aop = newAsmop (AOP_DIR);
657 aop->aopu.aop_dir = sym->rname ;
658 aop->size = getSize(sym->type);
659 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
660 pic16_allocDirReg( IC_LEFT(ic) );
665 /* special case for a function */
666 if (IS_FUNC(sym->type)) {
667 sym->aop = aop = newAsmop(AOP_IMMD);
668 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
669 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
670 strcpy(aop->aopu.aop_immd,sym->rname);
671 aop->size = FPTRSIZE;
672 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
678 /* only remaining is far space */
679 /* in which case DPTR gets the address */
680 sym->aop = aop = newAsmop(AOP_PCODE);
682 /* change the next if to 1 to revert to good old immediate code */
683 if(IN_CODESPACE(space)) {
684 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
685 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
686 PCOI(aop->aopu.pcop)->index = 0;
688 /* try to allocate via direct register */
689 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
690 // aop->size = getSize( sym->type );
693 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
694 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
697 if(!pic16_allocDirReg (IC_LEFT(ic)))
701 if(IN_DIRSPACE( space ))
703 else if(IN_CODESPACE( space ))
704 aop->size = FPTRSIZE;
705 else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
706 else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
711 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
713 /* if it is in code space */
714 if (IN_CODESPACE(space))
720 /*-----------------------------------------------------------------*/
721 /* aopForRemat - rematerialzes an object */
722 /*-----------------------------------------------------------------*/
723 static asmop *aopForRemat (operand *op) // x symbol *sym)
725 symbol *sym = OP_SYMBOL(op);
726 iCode *ic = NULL, *oldic;
727 asmop *aop = newAsmop(AOP_PCODE);
733 ic = sym->rematiCode;
735 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
737 if(IS_OP_POINTER(op)) {
738 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
744 // pic16_emitpcomment("ic: %s\n", printILine(ic));
747 val += (int) operandLitValue(IC_RIGHT(ic));
748 } else if (ic->op == '-') {
749 val -= (int) operandLitValue(IC_RIGHT(ic));
753 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
756 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
758 if(!op->isaddr)viaimmd++; else viaimmd=0;
760 /* set the following if to 1 to revert to good old immediate code */
761 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
764 DEBUGpic16_emitcode("%s:%d immediate", __FILE__, __LINE__);
766 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
769 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
771 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
774 PCOI(aop->aopu.pcop)->index = val;
776 DEBUGpic16_emitcode("%s:%d dir", __FILE__, __LINE__);
778 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
779 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
780 // aop->size = AOP_SIZE( IC_LEFT(ic) );
784 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
785 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
787 val, IS_PTR_CONST(operandType(op)));
789 val, IS_CODEPTR(operandType(op)));
792 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
794 pic16_allocDirReg (IC_LEFT(ic));
796 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
802 static int aopIdx (asmop *aop, int offset)
807 if(aop->type != AOP_REG)
810 return aop->aopu.aop_reg[offset]->rIdx;
813 /*-----------------------------------------------------------------*/
814 /* regsInCommon - two operands have some registers in common */
815 /*-----------------------------------------------------------------*/
816 static bool regsInCommon (operand *op1, operand *op2)
821 /* if they have registers in common */
822 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
825 sym1 = OP_SYMBOL(op1);
826 sym2 = OP_SYMBOL(op2);
828 if (sym1->nRegs == 0 || sym2->nRegs == 0)
831 for (i = 0 ; i < sym1->nRegs ; i++) {
836 for (j = 0 ; j < sym2->nRegs ;j++ ) {
840 if (sym2->regs[j] == sym1->regs[i])
848 /*-----------------------------------------------------------------*/
849 /* operandsEqu - equivalent */
850 /*-----------------------------------------------------------------*/
851 static bool operandsEqu ( operand *op1, operand *op2)
855 /* if they not symbols */
856 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
859 sym1 = OP_SYMBOL(op1);
860 sym2 = OP_SYMBOL(op2);
862 /* if both are itemps & one is spilt
863 and the other is not then false */
864 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
865 sym1->isspilt != sym2->isspilt )
868 /* if they are the same */
872 if (sym1->rname[0] && sym2->rname[0]
873 && strcmp (sym1->rname, sym2->rname) == 0)
877 /* if left is a tmp & right is not */
881 (sym1->usl.spillLoc == sym2))
888 (sym2->usl.spillLoc == sym1))
894 /*-----------------------------------------------------------------*/
895 /* pic16_sameRegs - two asmops have the same registers */
896 /*-----------------------------------------------------------------*/
897 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
904 if (aop1->type != AOP_REG ||
905 aop2->type != AOP_REG )
908 if (aop1->size != aop2->size )
911 for (i = 0 ; i < aop1->size ; i++ )
912 if (aop1->aopu.aop_reg[i] !=
913 aop2->aopu.aop_reg[i] )
919 /*-----------------------------------------------------------------*/
920 /* pic16_aopOp - allocates an asmop for an operand : */
921 /*-----------------------------------------------------------------*/
922 void pic16_aopOp (operand *op, iCode *ic, bool result)
931 // DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
933 /* if this a literal */
934 if (IS_OP_LITERAL(op)) {
935 op->aop = aop = newAsmop(AOP_LIT);
936 aop->aopu.aop_lit = op->operand.valOperand;
937 aop->size = getSize(operandType(op));
942 sym_link *type = operandType(op);
944 if(IS_PTR_CONST(type))
948 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
951 /* if already has a asmop then continue */
955 /* if the underlying symbol has a aop */
956 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
957 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
958 op->aop = OP_SYMBOL(op)->aop;
962 /* if this is a true symbol */
963 if (IS_TRUE_SYMOP(op)) {
964 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
965 op->aop = aopForSym(ic, op, result);
969 /* this is a temporary : this has
975 e) can be a return use only */
979 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
980 /* if the type is a conditional */
981 if (sym->regType == REG_CND) {
982 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
987 /* if it is spilt then two situations
989 b) has a spill location */
990 if (sym->isspilt || sym->nRegs == 0) {
992 DEBUGpic16_emitcode(";","%d",__LINE__);
993 /* rematerialize it NOW */
996 sym->aop = op->aop = aop =
998 aop->size = getSize(sym->type);
999 //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1006 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1007 aop->size = getSize(sym->type);
1008 for ( i = 0 ; i < 1 ; i++ ) {
1009 aop->aopu.aop_str[i] = accUse[i];
1010 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1012 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1013 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1021 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1022 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1023 //pic16_allocDirReg (IC_LEFT(ic));
1024 aop->size = getSize(sym->type);
1029 aop = op->aop = sym->aop = newAsmop(AOP_STR);
1030 aop->size = getSize(sym->type);
1031 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1032 aop->aopu.aop_str[i] = fReturn[i];
1034 DEBUGpic16_emitcode(";","%d",__LINE__);
1038 /* else spill location */
1039 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1040 /* force a new aop if sizes differ */
1041 sym->usl.spillLoc->aop = NULL;
1043 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1044 __FUNCTION__,__LINE__,
1045 sym->usl.spillLoc->rname,
1046 sym->rname, sym->usl.spillLoc->offset);
1048 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1049 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1050 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1052 sym->usl.spillLoc->offset, op);
1053 aop->size = getSize(sym->type);
1059 sym_link *type = operandType(op);
1061 if(IS_PTR_CONST(type))
1063 if(IS_CODEPTR(type))
1065 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1068 /* must be in a register */
1069 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1070 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1071 aop->size = sym->nRegs;
1072 for ( i = 0 ; i < sym->nRegs ;i++)
1073 aop->aopu.aop_reg[i] = sym->regs[i];
1076 /*-----------------------------------------------------------------*/
1077 /* pic16_freeAsmop - free up the asmop given to an operand */
1078 /*----------------------------------------------------------------*/
1079 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1096 /* depending on the asmop type only three cases need work AOP_RO
1097 , AOP_R1 && AOP_STK */
1099 switch (aop->type) {
1103 pic16_emitcode ("pop","ar0");
1107 bitVectUnSetBit(ic->rUsed,R0_IDX);
1113 pic16_emitcode ("pop","ar1");
1117 bitVectUnSetBit(ic->rUsed,R1_IDX);
1123 int stk = aop->aopu.aop_stk + aop->size;
1124 bitVectUnSetBit(ic->rUsed,R0_IDX);
1125 bitVectUnSetBit(ic->rUsed,R1_IDX);
1127 getFreePtr(ic,&aop,FALSE);
1129 if (options.stack10bit)
1131 /* I'm not sure what to do here yet... */
1134 "*** Warning: probably generating bad code for "
1135 "10 bit stack mode.\n");
1139 pic16_emitcode ("mov","a,_bp");
1140 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1141 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1143 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1147 pic16_emitcode("pop","acc");
1148 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1150 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1153 pic16_freeAsmop(op,NULL,ic,TRUE);
1155 pic16_emitcode("pop","ar0");
1160 pic16_emitcode("pop","ar1");
1168 /* all other cases just dealloc */
1172 OP_SYMBOL(op)->aop = NULL;
1173 /* if the symbol has a spill */
1175 SPIL_LOC(op)->aop = NULL;
1180 /*-----------------------------------------------------------------*/
1181 /* pic16_aopGet - for fetching value of the aop */
1182 /*-----------------------------------------------------------------*/
1183 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1188 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1190 /* offset is greater than size then zero */
1191 if (offset > (aop->size - 1) &&
1192 aop->type != AOP_LIT)
1195 /* depending on type */
1196 switch (aop->type) {
1200 sprintf (s,"%s",aop->aopu.aop_immd);
1203 sprintf(s,"(%s >> %d)",
1208 aop->aopu.aop_immd);
1209 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1210 rs = Safe_calloc(1,strlen(s)+1);
1216 sprintf(s,"(%s + %d)",
1219 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1221 sprintf(s,"%s",aop->aopu.aop_dir);
1222 rs = Safe_calloc(1,strlen(s)+1);
1228 // return aop->aopu.aop_reg[offset]->dname;
1230 return aop->aopu.aop_reg[offset]->name;
1233 //pic16_emitcode(";","%d",__LINE__);
1234 return aop->aopu.aop_dir;
1237 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1238 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1240 return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1243 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1244 rs = Safe_calloc(1,strlen(s)+1);
1249 aop->coff = offset ;
1250 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1253 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1255 return aop->aopu.aop_str[offset];
1259 pCodeOp *pcop = aop->aopu.pcop;
1260 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1262 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1263 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1264 sprintf(s,"%s", pcop->name);
1266 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1269 rs = Safe_calloc(1,strlen(s)+1);
1274 // pCodeOp *pcop = aop->aop
1279 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1280 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1281 "aopget got unsupported aop->type");
1286 /*-----------------------------------------------------------------*/
1287 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1288 /*-----------------------------------------------------------------*/
1289 pCodeOp *pic16_popGetTempReg(void)
1294 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1299 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1300 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1301 PCOR(pcop)->r->wasUsed=1;
1302 PCOR(pcop)->r->isFree=0;
1304 /* push value on stack */
1305 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1313 /*-----------------------------------------------------------------*/
1314 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1315 /*-----------------------------------------------------------------*/
1316 void pic16_popReleaseTempReg(pCodeOp *pcop)
1318 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1320 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1321 PCOR(pcop)->r->isFree = 1;
1323 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1326 /*-----------------------------------------------------------------*/
1327 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1328 /*-----------------------------------------------------------------*/
1329 pCodeOp *pic16_popGetLabel(unsigned int key)
1332 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1337 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1340 /*-----------------------------------------------------------------*/
1341 /* pic16_popCopyReg - copy a pcode operator */
1342 /*-----------------------------------------------------------------*/
1343 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1347 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1348 pcor->pcop.type = pc->pcop.type;
1350 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1351 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1353 pcor->pcop.name = NULL;
1356 pcor->rIdx = pc->rIdx;
1359 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1364 /*-----------------------------------------------------------------*/
1365 /* pic16_popGetLit - asm operator to pcode operator conversion */
1366 /*-----------------------------------------------------------------*/
1367 pCodeOp *pic16_popGetLit(unsigned int lit)
1369 return pic16_newpCodeOpLit(lit);
1372 /*-----------------------------------------------------------------*/
1373 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1374 /*-----------------------------------------------------------------*/
1375 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1377 return pic16_newpCodeOpLit2(lit, arg2);
1381 /*-----------------------------------------------------------------*/
1382 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1383 /*-----------------------------------------------------------------*/
1384 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1386 return pic16_newpCodeOpImmd(name, offset,index, 0);
1390 /*-----------------------------------------------------------------*/
1391 /* pic16_popGet - asm operator to pcode operator conversion */
1392 /*-----------------------------------------------------------------*/
1393 pCodeOp *pic16_popGetWithString(char *str)
1399 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1403 pcop = pic16_newpCodeOp(str,PO_STR);
1408 /*-----------------------------------------------------------------*/
1409 /* pic16_popRegFromString - */
1410 /*-----------------------------------------------------------------*/
1411 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1414 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1415 pcop->type = PO_DIR;
1417 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1418 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1423 pcop->name = Safe_calloc(1,strlen(str)+1);
1424 strcpy(pcop->name,str);
1426 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1428 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1429 if(PCOR(pcop)->r == NULL) {
1430 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1431 // __FUNCTION__, __LINE__, str, size, offset);
1432 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1434 //fprintf(stderr, "allocating new register -> %s\n", str);
1436 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1438 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d",__LINE__,pcop->name,size,offset);
1440 PCOR(pcop)->instance = offset;
1445 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1449 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1451 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1452 PCOR(pcop)->rIdx = rIdx;
1453 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1455 PCOR(pcop)->r->isFree = 0;
1456 PCOR(pcop)->r->wasUsed = 1;
1458 pcop->type = PCOR(pcop)->r->pc_type;
1463 /*---------------------------------------------------------------------------------*/
1464 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1466 /*---------------------------------------------------------------------------------*/
1467 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1472 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1474 /* comment the following check, so errors to throw up */
1475 // if(!pcop2)return NULL;
1477 temp = pic16_popGet(aop_dst, offset);
1478 pcop2->pcop2 = temp;
1485 /*--------------------------------------------------------------------------------.-*/
1486 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1487 /* VR 030601 , adapted by Hans Dorn */
1488 /*--------------------------------------------------------------------------------.-*/
1489 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1493 pcop2 = (pCodeOpReg2 *)src;
1501 /*---------------------------------------------------------------------------------*/
1502 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1503 /* movff instruction */
1504 /*---------------------------------------------------------------------------------*/
1505 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1510 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1511 pcop2->pcop2 = pic16_popCopyReg(dst);
1513 /* the pCodeOp may be already allocated */
1514 pcop2 = (pCodeOpReg2 *)(src);
1515 pcop2->pcop2 = (pCodeOp *)(dst);
1522 /*-----------------------------------------------------------------*/
1523 /* pic16_popGet - asm operator to pcode operator conversion */
1524 /*-----------------------------------------------------------------*/
1525 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1527 //char *s = buffer ;
1531 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1532 /* offset is greater than
1535 // if (offset > (aop->size - 1) &&
1536 // aop->type != AOP_LIT)
1537 // return NULL; //zero;
1539 /* depending on type */
1540 switch (aop->type) {
1546 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1547 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1554 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1555 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1559 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1561 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1563 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1565 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1566 PCOR(pcop)->rIdx = rIdx;
1567 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1568 PCOR(pcop)->r->wasUsed=1;
1569 PCOR(pcop)->r->isFree=0;
1571 PCOR(pcop)->instance = offset;
1572 pcop->type = PCOR(pcop)->r->pc_type;
1573 // rs = aop->aopu.aop_reg[offset]->name;
1574 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1578 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1579 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1585 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1586 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1590 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1592 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1594 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1595 // pcop->type = PO_GPR_REGISTER;
1596 PCOR(pcop)->rIdx = rIdx;
1597 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1598 PCOR(pcop)->r->wasUsed=1;
1599 PCOR(pcop)->r->isFree=0;
1601 PCOR(pcop)->instance = offset;
1602 pcop->type = PCOR(pcop)->r->pc_type;
1603 rs = aop->aopu.aop_reg[offset]->name;
1604 DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1609 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1611 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1612 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1613 //if(PCOR(pcop)->r == NULL)
1614 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1618 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1619 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1622 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1623 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1626 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1627 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1628 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1629 pcop->type = PCOR(pcop)->r->pc_type;
1630 pcop->name = PCOR(pcop)->r->name;
1636 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1638 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1639 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1641 switch( aop->aopu.pcop->type ) {
1642 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1643 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1645 assert( 0 ); /* should never reach here */;
1648 PCOI(pcop)->offset = offset;
1653 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1654 "pic16_popGet got unsupported aop->type");
1657 /*-----------------------------------------------------------------*/
1658 /* pic16_aopPut - puts a string for a aop */
1659 /*-----------------------------------------------------------------*/
1660 void pic16_aopPut (asmop *aop, char *s, int offset)
1665 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1667 if (aop->size && offset > ( aop->size - 1)) {
1668 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1669 "pic16_aopPut got offset > aop->size");
1673 /* will assign value to value */
1674 /* depending on where it is ofcourse */
1675 switch (aop->type) {
1678 sprintf(d,"(%s + %d)",
1679 aop->aopu.aop_dir,offset);
1680 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1683 sprintf(d,"%s",aop->aopu.aop_dir);
1686 DEBUGpic16_emitcode(";","%d",__LINE__);
1688 pic16_emitcode("movf","%s,w",s);
1689 pic16_emitcode("movwf","%s",d);
1692 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1693 if(offset >= aop->size) {
1694 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1697 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1700 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1707 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1708 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1711 strcmp(s,"r0") == 0 ||
1712 strcmp(s,"r1") == 0 ||
1713 strcmp(s,"r2") == 0 ||
1714 strcmp(s,"r3") == 0 ||
1715 strcmp(s,"r4") == 0 ||
1716 strcmp(s,"r5") == 0 ||
1717 strcmp(s,"r6") == 0 ||
1718 strcmp(s,"r7") == 0 )
1719 pic16_emitcode("mov","%s,%s ; %d",
1720 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1724 if(strcmp(s,"W")==0 )
1725 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
1727 pic16_emitcode("movwf","%s",
1728 aop->aopu.aop_reg[offset]->name);
1730 if(strcmp(s,zero)==0) {
1731 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1733 } else if(strcmp(s,"W")==0) {
1734 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1735 pcop->type = PO_GPR_REGISTER;
1737 PCOR(pcop)->rIdx = -1;
1738 PCOR(pcop)->r = NULL;
1740 DEBUGpic16_emitcode(";","%d",__LINE__);
1741 pcop->name = Safe_strdup(s);
1742 pic16_emitpcode(POC_MOVFW,pcop);
1743 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1744 } else if(strcmp(s,one)==0) {
1745 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1746 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1748 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1756 if (aop->type == AOP_DPTR2)
1762 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1763 "pic16_aopPut writting to code space");
1767 while (offset > aop->coff) {
1769 pic16_emitcode ("inc","dptr");
1772 while (offset < aop->coff) {
1774 pic16_emitcode("lcall","__decdptr");
1779 /* if not in accumulater */
1782 pic16_emitcode ("movx","@dptr,a");
1784 if (aop->type == AOP_DPTR2)
1792 while (offset > aop->coff) {
1794 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1796 while (offset < aop->coff) {
1798 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1804 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1809 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1811 if (strcmp(s,"r0") == 0 ||
1812 strcmp(s,"r1") == 0 ||
1813 strcmp(s,"r2") == 0 ||
1814 strcmp(s,"r3") == 0 ||
1815 strcmp(s,"r4") == 0 ||
1816 strcmp(s,"r5") == 0 ||
1817 strcmp(s,"r6") == 0 ||
1818 strcmp(s,"r7") == 0 ) {
1820 sprintf(buffer,"a%s",s);
1821 pic16_emitcode("mov","@%s,%s",
1822 aop->aopu.aop_ptr->name,buffer);
1824 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1829 if (strcmp(s,"a") == 0)
1830 pic16_emitcode("push","acc");
1832 pic16_emitcode("push","%s",s);
1837 /* if bit variable */
1838 if (!aop->aopu.aop_dir) {
1839 pic16_emitcode("clr","a");
1840 pic16_emitcode("rlc","a");
1843 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1846 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1849 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1851 lbl = newiTempLabel(NULL);
1853 if (strcmp(s,"a")) {
1856 pic16_emitcode("clr","c");
1857 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1858 pic16_emitcode("cpl","c");
1859 pic16_emitcode("","%05d_DS_:",lbl->key+100);
1860 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1867 if (strcmp(aop->aopu.aop_str[offset],s))
1868 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1873 if (!offset && (strcmp(s,"acc") == 0))
1876 if (strcmp(aop->aopu.aop_str[offset],s))
1877 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1881 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1882 "pic16_aopPut got unsupported aop->type");
1888 /*-----------------------------------------------------------------*/
1889 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1890 /*-----------------------------------------------------------------*/
1891 static void mov2w (asmop *aop, int offset)
1897 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
1900 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1902 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1907 /* push pcop into stack */
1908 void pic16_pushpCodeOp(pCodeOp *pcop)
1910 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1911 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1914 /* pop pcop from stack */
1915 void pic16_poppCodeOp(pCodeOp *pcop)
1917 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1921 /*-----------------------------------------------------------------*/
1922 /* pushw - pushes wreg to stack */
1923 /*-----------------------------------------------------------------*/
1926 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1927 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1931 /*-----------------------------------------------------------------*/
1932 /* pushaop - pushes aop to stack */
1933 /*-----------------------------------------------------------------*/
1934 void pushaop(asmop *aop, int offset)
1936 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1937 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1940 /*-----------------------------------------------------------------*/
1941 /* popaop - pops aop from stack */
1942 /*-----------------------------------------------------------------*/
1943 void popaop(asmop *aop, int offset)
1945 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
1946 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1949 void popaopidx(asmop *aop, int offset, int index)
1953 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1955 if(STACK_MODEL_LARGE)ofs++;
1957 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1958 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1961 /*-----------------------------------------------------------------*/
1962 /* reAdjustPreg - points a register back to where it should */
1963 /*-----------------------------------------------------------------*/
1964 static void reAdjustPreg (asmop *aop)
1968 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1970 if ((size = aop->size) <= 1)
1973 switch (aop->type) {
1977 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1981 if (aop->type == AOP_DPTR2)
1987 pic16_emitcode("lcall","__decdptr");
1990 if (aop->type == AOP_DPTR2)
2002 /*-----------------------------------------------------------------*/
2003 /* opIsGptr: returns non-zero if the passed operand is */
2004 /* a generic pointer type. */
2005 /*-----------------------------------------------------------------*/
2006 static int opIsGptr(operand *op)
2008 sym_link *type = operandType(op);
2010 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2011 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2019 /*-----------------------------------------------------------------*/
2020 /* pic16_getDataSize - get the operand data size */
2021 /*-----------------------------------------------------------------*/
2022 int pic16_getDataSize(operand *op)
2024 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2027 return AOP_SIZE(op);
2029 // tsd- in the pic port, the genptr size is 1, so this code here
2030 // fails. ( in the 8051 port, the size was 4).
2033 size = AOP_SIZE(op);
2034 if (size == GPTRSIZE)
2036 sym_link *type = operandType(op);
2037 if (IS_GENPTR(type))
2039 /* generic pointer; arithmetic operations
2040 * should ignore the high byte (pointer type).
2043 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2050 /*-----------------------------------------------------------------*/
2051 /* pic16_outAcc - output Acc */
2052 /*-----------------------------------------------------------------*/
2053 void pic16_outAcc(operand *result)
2056 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2057 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2060 size = pic16_getDataSize(result);
2062 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2065 /* unsigned or positive */
2067 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2072 /*-----------------------------------------------------------------*/
2073 /* pic16_outBitC - output a bit C */
2074 /* Move to result the value of Carry flag -- VR */
2075 /*-----------------------------------------------------------------*/
2076 void pic16_outBitC(operand *result)
2080 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2081 /* if the result is bit */
2082 if (AOP_TYPE(result) == AOP_CRY) {
2083 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2084 pic16_aopPut(AOP(result),"c",0);
2087 i = AOP_SIZE(result);
2089 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2091 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2094 pic16_emitcode("clr","a ; %d", __LINE__);
2095 pic16_emitcode("rlc","a");
2096 pic16_outAcc(result);
2101 /*-----------------------------------------------------------------*/
2102 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2103 /*-----------------------------------------------------------------*/
2104 void pic16_toBoolean(operand *oper)
2106 int size = AOP_SIZE(oper) - 1;
2109 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2111 if ( AOP_TYPE(oper) != AOP_ACC) {
2112 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2115 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2120 #if !defined(GEN_Not)
2121 /*-----------------------------------------------------------------*/
2122 /* genNot - generate code for ! operation */
2123 /*-----------------------------------------------------------------*/
2124 static void pic16_genNot (iCode *ic)
2129 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2130 /* assign asmOps to operand & result */
2131 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2132 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2134 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2135 /* if in bit space then a special case */
2136 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2137 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2138 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2139 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2141 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2142 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2143 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2148 size = AOP_SIZE(IC_LEFT(ic));
2150 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2151 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2152 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2155 pic16_toBoolean(IC_LEFT(ic));
2157 tlbl = newiTempLabel(NULL);
2158 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2159 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2160 pic16_outBitC(IC_RESULT(ic));
2163 /* release the aops */
2164 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2165 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2170 #if !defined(GEN_Cpl)
2171 /*-----------------------------------------------------------------*/
2172 /* genCpl - generate code for complement */
2173 /*-----------------------------------------------------------------*/
2174 static void pic16_genCpl (iCode *ic)
2180 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2181 /* assign asmOps to operand & result */
2182 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2183 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2185 /* if both are in bit space then
2187 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2188 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2190 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2191 pic16_emitcode("cpl","c");
2192 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2196 size = AOP_SIZE(IC_RESULT(ic));
2199 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2201 pic16_emitcode("cpl","a");
2202 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2204 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2205 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2207 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2208 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2216 /* release the aops */
2217 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2218 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2222 /*-----------------------------------------------------------------*/
2223 /* genUminusFloat - unary minus for floating points */
2224 /*-----------------------------------------------------------------*/
2225 static void genUminusFloat(operand *op,operand *result)
2227 int size ,offset =0 ;
2230 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2231 /* for this we just need to flip the
2232 first it then copy the rest in place */
2233 size = AOP_SIZE(op) - 1;
2234 l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2238 pic16_emitcode("cpl","acc.7");
2239 pic16_aopPut(AOP(result),"a",3);
2242 pic16_aopPut(AOP(result),
2243 pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2249 /*-----------------------------------------------------------------*/
2250 /* genUminus - unary minus code generation */
2251 /*-----------------------------------------------------------------*/
2252 static void genUminus (iCode *ic)
2255 sym_link *optype, *rtype;
2257 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2260 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2261 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2263 /* if both in bit space then special case */
2264 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2265 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2267 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2268 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2269 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2274 optype = operandType(IC_LEFT(ic));
2275 rtype = operandType(IC_RESULT(ic));
2277 /* if float then do float stuff */
2278 if (IS_FLOAT(optype)) {
2279 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2283 /* otherwise subtract from zero by taking the 2's complement */
2284 size = AOP_SIZE(IC_LEFT(ic));
2286 for(i=0; i<size; i++) {
2287 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2288 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)),i));
2290 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2291 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2295 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2296 for(i=1; i<size; i++) {
2298 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2302 /* release the aops */
2303 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2304 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2307 /*-----------------------------------------------------------------*/
2308 /* saveRegisters - will look for a call and save the registers */
2309 /*-----------------------------------------------------------------*/
2310 static void saveRegisters(iCode *lic)
2317 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2319 for (ic = lic ; ic ; ic = ic->next)
2320 if (ic->op == CALL || ic->op == PCALL)
2324 fprintf(stderr,"found parameter push with no function call\n");
2328 /* if the registers have been saved already then
2330 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2333 /* find the registers in use at this time
2334 and push them away to safety */
2335 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2339 if (options.useXstack) {
2340 if (bitVectBitValue(rsave,R0_IDX))
2341 pic16_emitcode("mov","b,r0");
2342 pic16_emitcode("mov","r0,%s",spname);
2343 for (i = 0 ; i < pic16_nRegs ; i++) {
2344 if (bitVectBitValue(rsave,i)) {
2346 pic16_emitcode("mov","a,b");
2348 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2349 pic16_emitcode("movx","@r0,a");
2350 pic16_emitcode("inc","r0");
2353 pic16_emitcode("mov","%s,r0",spname);
2354 if (bitVectBitValue(rsave,R0_IDX))
2355 pic16_emitcode("mov","r0,b");
2357 //for (i = 0 ; i < pic16_nRegs ; i++) {
2358 // if (bitVectBitValue(rsave,i))
2359 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2362 dtype = operandType(IC_LEFT(ic));
2363 if (currFunc && dtype &&
2364 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2365 IFFUNC_ISISR(currFunc->type) &&
2368 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2371 /*-----------------------------------------------------------------*/
2372 /* unsaveRegisters - pop the pushed registers */
2373 /*-----------------------------------------------------------------*/
2374 static void unsaveRegisters (iCode *ic)
2379 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2380 /* find the registers in use at this time
2381 and push them away to safety */
2382 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2385 if (options.useXstack) {
2386 pic16_emitcode("mov","r0,%s",spname);
2387 for (i = pic16_nRegs ; i >= 0 ; i--) {
2388 if (bitVectBitValue(rsave,i)) {
2389 pic16_emitcode("dec","r0");
2390 pic16_emitcode("movx","a,@r0");
2392 pic16_emitcode("mov","b,a");
2394 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2398 pic16_emitcode("mov","%s,r0",spname);
2399 if (bitVectBitValue(rsave,R0_IDX))
2400 pic16_emitcode("mov","r0,b");
2402 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2403 // if (bitVectBitValue(rsave,i))
2404 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2410 /*-----------------------------------------------------------------*/
2412 /*-----------------------------------------------------------------*/
2413 static void pushSide(operand * oper, int size)
2416 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2418 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2419 if (AOP_TYPE(oper) != AOP_REG &&
2420 AOP_TYPE(oper) != AOP_DIR &&
2422 pic16_emitcode("mov","a,%s",l);
2423 pic16_emitcode("push","acc");
2425 pic16_emitcode("push","%s",l);
2430 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2432 // (AOP(left)->aopu.pcop->type == PO_DIR)?
2434 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2435 pic16_emitpcode(POC_MOVFW, src);
2436 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2438 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2439 src, pic16_popGet(AOP(op), offset)));
2444 /*-----------------------------------------------------------------*/
2445 /* assignResultValue - assign results to oper, rescall==1 is */
2446 /* called from genCall() or genPCall() */
2447 /*-----------------------------------------------------------------*/
2448 static void assignResultValue(operand * oper, int rescall)
2450 int size = AOP_SIZE(oper);
2452 DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2453 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2456 /* assign result from a call/pcall function() */
2458 /* function results are stored in a special order,
2459 * see top of file with Function return policy, or manual */
2462 /* 8-bits, result in WREG */
2463 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2466 /* 16-bits, result in PRODL:WREG */
2467 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2471 /* 24-bits, result in PRODH:PRODL:WREG */
2472 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2476 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2477 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2480 /* >32-bits, result on stack, and FSR0 points to beginning.
2481 * Fix stack when done */
2484 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2485 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2487 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2492 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2493 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2494 if(STACK_MODEL_LARGE) {
2496 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2500 if(!GpsuedoStkPtr) {
2501 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2502 /* The last byte in the assignment is in W */
2504 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2509 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2510 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2512 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2518 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2520 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2530 /*-----------------------------------------------------------------*/
2531 /* genIpush - genrate code for pushing this gets a little complex */
2532 /*-----------------------------------------------------------------*/
2533 static void genIpush (iCode *ic)
2536 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2538 int size, offset = 0 ;
2542 /* if this is not a parm push : ie. it is spill push
2543 and spill push is always done on the local stack */
2544 if (!ic->parmPush) {
2546 /* and the item is spilt then do nothing */
2547 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2550 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2551 size = AOP_SIZE(IC_LEFT(ic));
2552 /* push it on the stack */
2554 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2559 pic16_emitcode("push","%s",l);
2564 /* this is a paramter push: in this case we call
2565 the routine to find the call and save those
2566 registers that need to be saved */
2569 /* then do the push */
2570 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2573 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2574 size = AOP_SIZE(IC_LEFT(ic));
2577 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2578 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2579 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2581 pic16_emitcode("mov","a,%s",l);
2582 pic16_emitcode("push","acc");
2584 pic16_emitcode("push","%s",l);
2587 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2591 /*-----------------------------------------------------------------*/
2592 /* genIpop - recover the registers: can happen only for spilling */
2593 /*-----------------------------------------------------------------*/
2594 static void genIpop (iCode *ic)
2596 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2601 /* if the temp was not pushed then */
2602 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2605 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2606 size = AOP_SIZE(IC_LEFT(ic));
2609 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2612 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2616 /*-----------------------------------------------------------------*/
2617 /* unsaverbank - restores the resgister bank from stack */
2618 /*-----------------------------------------------------------------*/
2619 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2621 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2627 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2629 if (options.useXstack) {
2631 r = getFreePtr(ic,&aop,FALSE);
2634 pic16_emitcode("mov","%s,_spx",r->name);
2635 pic16_emitcode("movx","a,@%s",r->name);
2636 pic16_emitcode("mov","psw,a");
2637 pic16_emitcode("dec","%s",r->name);
2640 pic16_emitcode ("pop","psw");
2643 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2644 if (options.useXstack) {
2645 pic16_emitcode("movx","a,@%s",r->name);
2646 //pic16_emitcode("mov","(%s+%d),a",
2647 // regspic16[i].base,8*bank+regspic16[i].offset);
2648 pic16_emitcode("dec","%s",r->name);
2651 pic16_emitcode("pop",""); //"(%s+%d)",
2652 //regspic16[i].base,8*bank); //+regspic16[i].offset);
2655 if (options.useXstack) {
2657 pic16_emitcode("mov","_spx,%s",r->name);
2658 pic16_freeAsmop(NULL,aop,ic,TRUE);
2664 /*-----------------------------------------------------------------*/
2665 /* saverbank - saves an entire register bank on the stack */
2666 /*-----------------------------------------------------------------*/
2667 static void saverbank (int bank, iCode *ic, bool pushPsw)
2669 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2675 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2676 if (options.useXstack) {
2679 r = getFreePtr(ic,&aop,FALSE);
2680 pic16_emitcode("mov","%s,_spx",r->name);
2684 for (i = 0 ; i < pic16_nRegs ;i++) {
2685 if (options.useXstack) {
2686 pic16_emitcode("inc","%s",r->name);
2687 //pic16_emitcode("mov","a,(%s+%d)",
2688 // regspic16[i].base,8*bank+regspic16[i].offset);
2689 pic16_emitcode("movx","@%s,a",r->name);
2691 pic16_emitcode("push","");// "(%s+%d)",
2692 //regspic16[i].base,8*bank+regspic16[i].offset);
2696 if (options.useXstack) {
2697 pic16_emitcode("mov","a,psw");
2698 pic16_emitcode("movx","@%s,a",r->name);
2699 pic16_emitcode("inc","%s",r->name);
2700 pic16_emitcode("mov","_spx,%s",r->name);
2701 pic16_freeAsmop (NULL,aop,ic,TRUE);
2704 pic16_emitcode("push","psw");
2706 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2714 /*-----------------------------------------------------------------*/
2715 /* genCall - generates a call statement */
2716 /*-----------------------------------------------------------------*/
2717 static void genCall (iCode *ic)
2722 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2724 /* if caller saves & we have not saved then */
2728 /* if we are calling a function that is not using
2729 * the same register bank then we need to save the
2730 * destination registers on the stack */
2731 dtype = operandType(IC_LEFT(ic));
2732 if (currFunc && dtype &&
2733 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2734 IFFUNC_ISISR(currFunc->type) &&
2737 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2739 /* if send set is not empty the assign */
2743 /* For the Pic port, there is no data stack.
2744 * So parameters passed to functions are stored
2745 * in registers. (The pCode optimizer will get
2746 * rid of most of these :). */
2748 int psuedoStkPtr=-1;
2749 int firstTimeThruLoop = 1;
2751 _G.sendSet = reverseSet(_G.sendSet);
2753 /* First figure how many parameters are getting passed */
2754 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2755 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2756 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2757 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2760 stackParms = psuedoStkPtr;
2762 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2763 int size, offset = 0;
2765 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2766 size = AOP_SIZE(IC_LEFT(sic));
2769 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2770 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2771 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2773 if(!firstTimeThruLoop) {
2774 /* If this is not the first time we've been through the loop
2775 * then we need to save the parameter in a temporary
2776 * register. The last byte of the last parameter is
2780 --psuedoStkPtr; // sanity check
2783 firstTimeThruLoop=0;
2785 mov2w (AOP(IC_LEFT(sic)), offset);
2788 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2794 pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2795 OP_SYMBOL(IC_LEFT(ic))->rname :
2796 OP_SYMBOL(IC_LEFT(ic))->name));
2799 /* if we need assign a result value */
2800 if ((IS_ITEMP(IC_RESULT(ic)) &&
2801 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2802 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2803 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2806 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2809 assignResultValue(IC_RESULT(ic), 1);
2811 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2812 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2814 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2818 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2819 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2820 if(STACK_MODEL_LARGE) {
2822 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2826 /* adjust the stack for parameters if required */
2827 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2829 if (ic->parmBytes) {
2832 if (ic->parmBytes > 3) {
2833 pic16_emitcode("mov","a,%s",spname);
2834 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2835 pic16_emitcode("mov","%s,a",spname);
2837 for ( i = 0 ; i < ic->parmBytes ;i++)
2838 pic16_emitcode("dec","%s",spname);
2842 /* if register bank was saved then pop them */
2844 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2846 /* if we hade saved some registers then unsave them */
2847 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2848 unsaveRegisters (ic);
2854 /*-----------------------------------------------------------------*/ // patch 14
2855 /* genPcall - generates a call by pointer statement */
2856 /*-----------------------------------------------------------------*/
2858 // new version, created from genCall
2860 static void genPcall (iCode *ic)
2864 symbol *retlbl = newiTempLabel(NULL);
2865 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2867 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2869 /* if caller saves & we have not saved then */
2873 /* if we are calling a function that is not using
2874 * the same register bank then we need to save the
2875 * destination registers on the stack */
2876 dtype = operandType(IC_LEFT(ic));
2877 if (currFunc && dtype &&
2878 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2879 IFFUNC_ISISR(currFunc->type) &&
2882 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2884 /* if send set is not empty the assign */
2888 /* For the Pic port, there is no data stack.
2889 * So parameters passed to functions are stored
2890 * in registers. (The pCode optimizer will get
2891 * rid of most of these :). */
2893 int psuedoStkPtr=-1;
2894 int firstTimeThruLoop = 1;
2896 _G.sendSet = reverseSet(_G.sendSet);
2898 /* First figure how many parameters are getting passed */
2899 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2900 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2901 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2902 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2905 stackParms = psuedoStkPtr;
2907 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2908 int size, offset = 0;
2910 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2911 size = AOP_SIZE(IC_LEFT(sic));
2914 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2915 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2916 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2918 if(!firstTimeThruLoop) {
2919 /* If this is not the first time we've been through the loop
2920 * then we need to save the parameter in a temporary
2921 * register. The last byte of the last parameter is
2925 --psuedoStkPtr; // sanity check
2928 firstTimeThruLoop=0;
2930 mov2w (AOP(IC_LEFT(sic)), offset);
2933 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2938 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2940 // push return address
2941 // push $ on return stack, then replace with retlbl
2943 pic16_emitpcodeNULLop(POC_PUSH);
2945 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2946 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2947 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2948 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2949 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2950 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2952 /* make the call by writing the pointer into pc */
2953 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
2954 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
2956 // note: MOVFF to PCL not allowed
2957 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
2958 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2961 // pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key));
2962 // pic16_emitpcodeNULLop(POC_NOP);
2963 // pic16_emitpcodeNULLop(POC_NOP);
2965 /* return address is here: (X) */
2966 pic16_emitpLabelFORCE(retlbl->key);
2968 // pic16_emitpcodeNULLop(POC_NOP);
2970 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2973 /* if we need assign a result value */
2974 if ((IS_ITEMP(IC_RESULT(ic)) &&
2975 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2976 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2977 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2980 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2983 assignResultValue(IC_RESULT(ic), 1);
2985 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2986 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2988 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2992 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2993 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2994 if(STACK_MODEL_LARGE) {
2996 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3000 /* adjust the stack for parameters if required */
3001 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3003 if (ic->parmBytes) {
3006 if (ic->parmBytes > 3) {
3007 pic16_emitcode("mov","a,%s",spname);
3008 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3009 pic16_emitcode("mov","%s,a",spname);
3011 for ( i = 0 ; i < ic->parmBytes ;i++)
3012 pic16_emitcode("dec","%s",spname);
3015 /* if register bank was saved then pop them */
3017 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3019 /* if we hade saved some registers then unsave them */
3020 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3021 unsaveRegisters (ic);
3026 // old version, kept for reference
3028 /*-----------------------------------------------------------------*/
3029 /* genPcall - generates a call by pointer statement */
3030 /*-----------------------------------------------------------------*/
3031 static void genPcall (iCode *ic)
3034 symbol *rlbl = newiTempLabel(NULL);
3037 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3038 /* if caller saves & we have not saved then */
3042 /* if we are calling a function that is not using
3043 the same register bank then we need to save the
3044 destination registers on the stack */
3045 dtype = operandType(IC_LEFT(ic));
3046 if (currFunc && dtype &&
3047 IFFUNC_ISISR(currFunc->type) &&
3048 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3049 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3052 /* push the return address on to the stack */
3053 pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3054 pic16_emitcode("push","acc");
3055 pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3056 pic16_emitcode("push","acc");
3058 if (options.model == MODEL_FLAT24)
3060 pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3061 pic16_emitcode("push","acc");
3064 /* now push the calling address */
3065 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3067 pushSide(IC_LEFT(ic), FPTRSIZE);
3069 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3071 /* if send set is not empty the assign */
3075 for (sic = setFirstItem(_G.sendSet) ; sic ;
3076 sic = setNextItem(_G.sendSet)) {
3077 int size, offset = 0;
3078 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3079 size = AOP_SIZE(IC_LEFT(sic));
3081 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3083 if (strcmp(l,fReturn[offset]))
3084 pic16_emitcode("mov","%s,%s",
3089 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3094 pic16_emitcode("ret","");
3095 pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3098 /* if we need assign a result value */
3099 if ((IS_ITEMP(IC_RESULT(ic)) &&
3100 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3101 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3102 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3105 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3108 assignResultValue(IC_RESULT(ic), 1);
3110 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3113 /* adjust the stack for parameters if
3115 if (ic->parmBytes) {
3117 if (ic->parmBytes > 3) {
3118 pic16_emitcode("mov","a,%s",spname);
3119 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3120 pic16_emitcode("mov","%s,a",spname);
3122 for ( i = 0 ; i < ic->parmBytes ;i++)
3123 pic16_emitcode("dec","%s",spname);
3127 /* if register bank was saved then unsave them */
3128 if (currFunc && dtype &&
3129 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3130 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3132 /* if we hade saved some registers then
3135 unsaveRegisters (ic);
3141 /*-----------------------------------------------------------------*/
3142 /* resultRemat - result is rematerializable */
3143 /*-----------------------------------------------------------------*/
3144 static int resultRemat (iCode *ic)
3146 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3147 if (SKIP_IC(ic) || ic->op == IFX)
3150 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3151 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3152 if (sym->remat && !POINTER_SET(ic))
3159 #if defined(__BORLANDC__) || defined(_MSC_VER)
3160 #define STRCASECMP stricmp
3162 #define STRCASECMP strcasecmp
3166 /*-----------------------------------------------------------------*/
3167 /* inExcludeList - return 1 if the string is in exclude Reg list */
3168 /*-----------------------------------------------------------------*/
3169 static bool inExcludeList(char *s)
3171 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3174 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3175 if (options.excludeRegs[i] &&
3176 STRCASECMP(options.excludeRegs[i],"none") == 0)
3179 for ( i = 0 ; options.excludeRegs[i]; i++) {
3180 if (options.excludeRegs[i] &&
3181 STRCASECMP(s,options.excludeRegs[i]) == 0)
3188 /*-----------------------------------------------------------------*/
3189 /* genFunction - generated code for function entry */
3190 /*-----------------------------------------------------------------*/
3191 static void genFunction (iCode *ic)
3196 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3198 pic16_labelOffset += (max_key+4);
3203 ftype = operandType(IC_LEFT(ic));
3204 sym = OP_SYMBOL(IC_LEFT(ic));
3206 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3207 /* create an absolute section at the interrupt vector:
3208 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3216 sym = OP_SYMBOL( IC_LEFT(ic));
3218 if(interrupts[i]->name
3219 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3226 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3227 __FILE__, __LINE__, sym->name);
3230 _G.interruptvector = found;
3233 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3234 asym = newSymbol(asymname, 0);
3236 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3237 pic16_addpBlock( apb );
3239 pic16_addpCode2pBlock(apb,
3240 pic16_newpCodeCharP(";-----------------------------------------"));
3243 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3245 pic16_addpCode2pBlock(apb,
3246 pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3248 /* mark the end of this tiny function */
3249 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3254 abSym = Safe_calloc(1, sizeof(absSym));
3255 abSym->name = Safe_strdup( asymname );
3257 switch( _G.interruptvector ) {
3258 case 0: abSym->address = 0x000000; break;
3259 case 1: abSym->address = 0x000008; break;
3260 case 2: abSym->address = 0x000018; break;
3263 /* relocate interrupt vectors if needed */
3264 abSym->address += pic16_options.ivt_loc;
3266 addSet(&absSymSet, abSym);
3271 /* create the function header */
3272 pic16_emitcode(";","-----------------------------------------");
3273 pic16_emitcode(";"," function %s",sym->name);
3274 pic16_emitcode(";","-----------------------------------------");
3276 pic16_emitcode("","%s:",sym->rname);
3277 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3283 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3284 if(!strcmp(ab->name, sym->name)) {
3285 pic16_pBlockConvert2Absolute(pb);
3292 if(IFFUNC_ISNAKED(ftype)) {
3293 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3297 /* if critical function then turn interrupts off */
3298 if (IFFUNC_ISCRITICAL(ftype))
3299 pic16_emitcode("clr","ea");
3301 /* if this is an interrupt service routine then
3302 * save acc, b, dpl, dph */
3303 if (IFFUNC_ISISR(sym->type)) {
3305 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3306 if(!(_G.interruptvector == 1)) {
3308 /* do not save WREG,STATUS,BSR for high priority interrupts
3309 * because they are stored in the hardware shadow registers already */
3311 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3312 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3313 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3316 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3317 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3318 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3319 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3321 // pic16_pBlockConvert2ISR(pb);
3323 /* if any registers used */
3324 if (sym->regsUsed) {
3325 /* save the registers used */
3326 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3327 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3328 if (bitVectBitValue(sym->regsUsed,i)) {
3330 fprintf(stderr, "%s:%d function %s uses register %s\n",
3331 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3332 pic16_regWithIdx(i)->name);
3335 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3338 if(!pic16_regWithIdx(i)->wasUsed) {
3339 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3340 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3342 pic16_regWithIdx(i)->wasUsed = 1;
3348 /* emit code to setup stack frame if user enabled,
3349 * and function is not main() */
3351 // fprintf(stderr, "function name: %s\n", sym->name);
3352 if(strcmp(sym->name, "main")) {
3353 if(/*!options.ommitFramePtr || */sym->regsUsed) {
3354 /* setup the stack frame */
3355 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3356 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3357 if(STACK_MODEL_LARGE)
3358 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3362 /* if callee-save to be used for this function
3363 * then save the registers being used in this function */
3364 // if (IFFUNC_CALLEESAVES(sym->type))
3368 // fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3370 // pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3372 /* if any registers used */
3373 if (sym->regsUsed) {
3374 /* save the registers used */
3375 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3376 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3377 if (bitVectBitValue(sym->regsUsed,i)) {
3380 fprintf(stderr, "%s:%d function %s uses register %s (wasUsed: %d, %p)\n",
3381 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3382 pic16_regWithIdx(i)->name,
3383 pic16_regWithIdx(i)->wasUsed,
3384 pic16_regWithIdx(i));
3387 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3389 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3390 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3391 // &pic16_pc_postdec1, 0));
3395 if(!pic16_regWithIdx(i)->wasUsed) {
3396 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3397 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3399 pic16_regWithIdx(i)->wasUsed = 1;
3411 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3413 if (options.useXstack) {
3414 pic16_emitcode("mov","r0,%s",spname);
3415 pic16_emitcode("mov","a,_bp");
3416 pic16_emitcode("movx","@r0,a");
3417 pic16_emitcode("inc","%s",spname);
3419 /* set up the stack */
3420 pic16_emitcode ("push","_bp"); /* save the callers stack */
3422 pic16_emitcode ("mov","_bp,%s",spname);
3425 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3427 /* adjust the stack for the function */
3432 werror(W_STACK_OVERFLOW,sym->name);
3434 if (i > 3 && sym->recvSize < 4) {
3435 pic16_emitcode ("mov","a,sp");
3436 pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3437 pic16_emitcode ("mov","sp,a");
3440 pic16_emitcode("inc","sp");
3444 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3446 pic16_emitcode ("mov","a,_spx");
3447 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3448 pic16_emitcode ("mov","_spx,a");
3453 /*-----------------------------------------------------------------*/
3454 /* genEndFunction - generates epilogue for functions */
3455 /*-----------------------------------------------------------------*/
3456 static void genEndFunction (iCode *ic)
3458 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3460 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3462 if(IFFUNC_ISNAKED(sym->type)) {
3463 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3468 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3470 pic16_emitcode ("mov","%s,_bp",spname);
3474 /* if use external stack but some variables were
3475 added to the local stack then decrement the
3477 if (options.useXstack && sym->stack) {
3478 pic16_emitcode("mov","a,sp");
3479 pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3480 pic16_emitcode("mov","sp,a");
3485 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3486 if (options.useXstack) {
3487 pic16_emitcode("mov","r0,%s",spname);
3488 pic16_emitcode("movx","a,@r0");
3489 pic16_emitcode("mov","_bp,a");
3490 pic16_emitcode("dec","%s",spname);
3494 pic16_emitcode ("pop","_bp");
3499 if (IFFUNC_ISISR(sym->type)) {
3500 /* now we need to restore the registers */
3501 /* if any registers used */
3502 if (sym->regsUsed) {
3505 /* restore registers used */
3506 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3507 for ( i = sym->regsUsed->size; i >= 0; i--) {
3508 if (bitVectBitValue(sym->regsUsed,i)) {
3510 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3511 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3512 // pic16_regWithIdx(i)->name);
3514 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3516 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3517 // &pic16_pc_preinc1,
3518 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3524 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3525 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3526 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3527 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3529 if(!(_G.interruptvector == 1)) {
3530 /* do not restore interrupt vector for WREG,STATUS,BSR
3531 * for high priority interrupt, see genFunction */
3533 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3534 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3535 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3538 _G.interruptvector = 0; /* sanity check */
3540 // pic16_pBlockConvert2ISR(pb);
3543 /* if debug then send end of function */
3544 /* if (options.debug && currFunc) */
3546 debugFile->writeEndFunction (currFunc, ic, 1);
3549 pic16_emitpcodeNULLop(POC_RETFIE);
3551 if (IFFUNC_ISCRITICAL(sym->type))
3552 pic16_emitcode("setb","ea");
3555 // pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3557 /* if any registers used */
3558 if (sym->regsUsed) {
3560 /* save the registers used */
3561 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3562 for ( i = sym->regsUsed->size; i >= 0; i--) {
3563 if (bitVectBitValue(sym->regsUsed,i)) {
3565 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3566 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3567 // pic16_regWithIdx(i)->name);
3569 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3571 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3572 // &pic16_pc_preinc1,
3573 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3580 // pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3581 /* if debug then send end of function */
3583 debugFile->writeEndFunction (currFunc, ic, 1);
3586 /* insert code to restore stack frame, if user enabled it
3587 * and function is not main() */
3590 if(strcmp(sym->name, "main")) {
3591 if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3592 /* restore stack frame */
3593 if(STACK_MODEL_LARGE)
3594 pic16_emitpcode(POC_MOVFF,
3595 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3596 pic16_emitpcode(POC_MOVFF,
3597 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3601 pic16_emitcode ("return","");
3602 pic16_emitpcodeNULLop(POC_RETURN);
3604 /* Mark the end of a function */
3605 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3611 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3615 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3617 if(dest->type != PO_WREG)
3618 pic16_emitpcode(POC_MOVWF, dest);
3620 if(dest->type == PO_WREG && (offset == 0)) {
3621 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3625 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3626 pic16_popGet(AOP(op), offset), dest));
3630 /*-----------------------------------------------------------------*/
3631 /* genRet - generate code for return statement */
3632 /*-----------------------------------------------------------------*/
3633 static void genRet (iCode *ic)
3638 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3639 /* if we have no return value then
3640 * just generate the "ret" */
3645 /* we have something to return then
3646 * move the return value into place */
3647 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3648 size = AOP_SIZE(IC_LEFT(ic));
3652 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3653 // pic16_emitpcode(POC_MOVFF,
3654 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3657 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3658 // pic16_emitpcode(POC_MOVFF,
3659 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3662 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3663 // pic16_emitpcode(POC_MOVFF,
3664 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3667 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3669 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3670 // pic16_emitpcode(POC_MOVFF,
3671 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3674 /* >32-bits, setup stack and FSR0 */
3676 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3677 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3679 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3681 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3686 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3687 pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3689 if(STACK_MODEL_LARGE) {
3690 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3691 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3693 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3698 /* old code, left here for reference -- VR */
3702 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3704 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3705 pic16_emitpcomment("push %s",l);
3708 DEBUGpic16_emitcode(";", "%d", __LINE__);
3709 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3710 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3712 if (strcmp(fReturn[offset],l)) {
3713 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3714 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3715 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3717 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3721 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3731 if (strcmp(fReturn[pushed],"a"))
3732 pic16_emitcode("pop",fReturn[pushed]);
3734 pic16_emitcode("pop","acc");
3740 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3743 /* generate a jump to the return label
3744 * if the next is not the return statement */
3745 if (!(ic->next && ic->next->op == LABEL
3746 && IC_LABEL(ic->next) == returnLabel)) {
3748 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3749 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3753 /*-----------------------------------------------------------------*/
3754 /* genLabel - generates a label */
3755 /*-----------------------------------------------------------------*/
3756 static void genLabel (iCode *ic)
3760 /* special case never generate */
3761 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3762 if (IC_LABEL(ic) == entryLabel)
3765 pic16_emitpLabel(IC_LABEL(ic)->key);
3766 pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3769 /*-----------------------------------------------------------------*/
3770 /* genGoto - generates a goto */
3771 /*-----------------------------------------------------------------*/
3773 static void genGoto (iCode *ic)
3775 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3776 pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3780 /*-----------------------------------------------------------------*/
3781 /* genMultbits :- multiplication of bits */
3782 /*-----------------------------------------------------------------*/
3783 static void genMultbits (operand *left,
3787 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3789 if(!pic16_sameRegs(AOP(result),AOP(right)))
3790 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3792 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3793 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3794 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3799 /*-----------------------------------------------------------------*/
3800 /* genMultOneByte : 8 bit multiplication & division */
3801 /*-----------------------------------------------------------------*/
3802 static void genMultOneByte (operand *left,
3807 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3808 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3809 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3811 /* (if two literals, the value is computed before) */
3812 /* if one literal, literal on the right */
3813 if (AOP_TYPE(left) == AOP_LIT){
3819 /* size is already checked in genMult == 1 */
3820 // size = AOP_SIZE(result);
3822 if (AOP_TYPE(right) == AOP_LIT){
3823 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3824 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3825 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3826 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3828 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3829 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3830 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3831 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3834 pic16_genMult8X8_8 (left, right,result);
3837 /*-----------------------------------------------------------------*/
3838 /* genMultOneWord : 16 bit multiplication */
3839 /*-----------------------------------------------------------------*/
3840 static void genMultOneWord (operand *left,
3845 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3846 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3847 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3849 /* (if two literals, the value is computed before)
3850 * if one literal, literal on the right */
3851 if (AOP_TYPE(left) == AOP_LIT){
3857 /* size is checked already == 2 */
3858 // size = AOP_SIZE(result);
3860 if (AOP_TYPE(right) == AOP_LIT) {
3861 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3862 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3863 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3864 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3866 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3867 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3868 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3869 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3872 pic16_genMult16X16_16(left, right,result);
3875 /*-----------------------------------------------------------------*/
3876 /* genMultOneLong : 32 bit multiplication */
3877 /*-----------------------------------------------------------------*/
3878 static void genMultOneLong (operand *left,
3883 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3884 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3885 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3887 /* (if two literals, the value is computed before)
3888 * if one literal, literal on the right */
3889 if (AOP_TYPE(left) == AOP_LIT){
3895 /* size is checked already == 4 */
3896 // size = AOP_SIZE(result);
3898 if (AOP_TYPE(right) == AOP_LIT) {
3899 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3900 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3901 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3902 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3904 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3905 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3906 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3907 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3910 pic16_genMult32X32_32(left, right,result);
3915 /*-----------------------------------------------------------------*/
3916 /* genMult - generates code for multiplication */
3917 /*-----------------------------------------------------------------*/
3918 static void genMult (iCode *ic)
3920 operand *left = IC_LEFT(ic);
3921 operand *right = IC_RIGHT(ic);
3922 operand *result= IC_RESULT(ic);
3924 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3925 /* assign the amsops */
3926 pic16_aopOp (left,ic,FALSE);
3927 pic16_aopOp (right,ic,FALSE);
3928 pic16_aopOp (result,ic,TRUE);
3930 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3932 /* special cases first *
3934 if (AOP_TYPE(left) == AOP_CRY
3935 && AOP_TYPE(right)== AOP_CRY) {
3936 genMultbits(left,right,result);
3940 /* if both are of size == 1 */
3941 if(AOP_SIZE(left) == 1
3942 && AOP_SIZE(right) == 1) {
3943 genMultOneByte(left,right,result);
3947 /* if both are of size == 2 */
3948 if(AOP_SIZE(left) == 2
3949 && AOP_SIZE(right) == 2) {
3950 genMultOneWord(left, right, result);
3954 /* if both are of size == 4 */
3955 if(AOP_SIZE(left) == 4
3956 && AOP_SIZE(right) == 4) {
3957 genMultOneLong(left, right, result);
3961 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3964 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3965 /* should have been converted to function call */
3969 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3970 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3971 pic16_freeAsmop(result,NULL,ic,TRUE);
3974 /*-----------------------------------------------------------------*/
3975 /* genDivbits :- division of bits */
3976 /*-----------------------------------------------------------------*/
3977 static void genDivbits (operand *left,
3984 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3985 /* the result must be bit */
3986 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3987 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3991 pic16_emitcode("div","ab");
3992 pic16_emitcode("rrc","a");
3993 pic16_aopPut(AOP(result),"c",0);
3996 /*-----------------------------------------------------------------*/
3997 /* genDivOneByte : 8 bit division */
3998 /*-----------------------------------------------------------------*/
3999 static void genDivOneByte (operand *left,
4003 sym_link *opetype = operandType(result);
4008 /* result = divident / divisor
4009 * - divident may be a register or a literal,
4010 * - divisor may be a register or a literal,
4011 * so there are 3 cases (literal / literal is optimized
4012 * by the front-end) to handle.
4013 * In addition we must handle signed and unsigned, which
4014 * result in 6 final different cases -- VR */
4016 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4017 size = AOP_SIZE(result) - 1;
4019 /* signed or unsigned */
4020 if (SPEC_USIGN(opetype)) {
4021 pCodeOp *pct1, /* count */
4024 symbol *label1, *label2, *label3;;
4027 /* unsigned is easy */
4029 pct1 = pic16_popGetTempReg();
4030 pct2 = pic16_popGetTempReg();
4031 pct3 = pic16_popGetTempReg();
4033 label1 = newiTempLabel(NULL);
4034 label2 = newiTempLabel(NULL);
4035 label3 = newiTempLabel(NULL);
4037 /* the following algorithm is extracted from divuint.c */
4039 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4040 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4042 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4044 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4046 pic16_emitpLabel(label1->key);
4049 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4053 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4057 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4059 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4060 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4062 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4063 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4064 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4066 pic16_emitpLabel( label3->key );
4067 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4068 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4072 pic16_emitpLabel(label2->key);
4073 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4074 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4075 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4077 /* result is in wreg */
4078 if(AOP_TYPE(result) != AOP_ACC)
4079 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4081 pic16_popReleaseTempReg( pct3 );
4082 pic16_popReleaseTempReg( pct2 );
4083 pic16_popReleaseTempReg( pct1 );
4088 /* signed is a little bit more difficult */
4090 /* save the signs of the operands */
4091 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4093 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4094 pic16_emitcode("push","acc"); /* save it on the stack */
4096 /* now sign adjust for both left & right */
4097 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4099 lbl = newiTempLabel(NULL);
4100 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4101 pic16_emitcode("cpl","a");
4102 pic16_emitcode("inc","a");
4103 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4104 pic16_emitcode("mov","b,a");
4106 /* sign adjust left side */
4107 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4110 lbl = newiTempLabel(NULL);
4111 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4112 pic16_emitcode("cpl","a");
4113 pic16_emitcode("inc","a");
4114 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4116 /* now the division */
4117 pic16_emitcode("div","ab");
4118 /* we are interested in the lower order
4120 pic16_emitcode("mov","b,a");
4121 lbl = newiTempLabel(NULL);
4122 pic16_emitcode("pop","acc");
4123 /* if there was an over flow we don't
4124 adjust the sign of the result */
4125 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4126 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4128 pic16_emitcode("clr","a");
4129 pic16_emitcode("subb","a,b");
4130 pic16_emitcode("mov","b,a");
4131 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4133 /* now we are done */
4134 pic16_aopPut(AOP(result),"b",0);
4136 pic16_emitcode("mov","c,b.7");
4137 pic16_emitcode("subb","a,acc");
4140 pic16_aopPut(AOP(result),"a",offset++);
4144 /*-----------------------------------------------------------------*/
4145 /* genDiv - generates code for division */
4146 /*-----------------------------------------------------------------*/
4147 static void genDiv (iCode *ic)
4149 operand *left = IC_LEFT(ic);
4150 operand *right = IC_RIGHT(ic);
4151 operand *result= IC_RESULT(ic);
4154 /* Division is a very lengthy algorithm, so it is better
4155 * to call support routines than inlining algorithm.
4156 * Division functions written here just in case someone
4157 * wants to inline and not use the support libraries -- VR */
4159 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4160 /* assign the amsops */
4161 pic16_aopOp (left,ic,FALSE);
4162 pic16_aopOp (right,ic,FALSE);
4163 pic16_aopOp (result,ic,TRUE);
4165 /* special cases first */
4167 if (AOP_TYPE(left) == AOP_CRY &&
4168 AOP_TYPE(right)== AOP_CRY) {
4169 genDivbits(left,right,result);
4173 /* if both are of size == 1 */
4174 if (AOP_SIZE(left) == 1 &&
4175 AOP_SIZE(right) == 1 ) {
4176 genDivOneByte(left,right,result);
4180 /* should have been converted to function call */
4183 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4184 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4185 pic16_freeAsmop(result,NULL,ic,TRUE);
4188 /*-----------------------------------------------------------------*/
4189 /* genModbits :- modulus of bits */
4190 /*-----------------------------------------------------------------*/
4191 static void genModbits (operand *left,
4198 /* the result must be bit */
4199 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4200 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4204 pic16_emitcode("div","ab");
4205 pic16_emitcode("mov","a,b");
4206 pic16_emitcode("rrc","a");
4207 pic16_aopPut(AOP(result),"c",0);
4210 /*-----------------------------------------------------------------*/
4211 /* genModOneByte : 8 bit modulus */
4212 /*-----------------------------------------------------------------*/
4213 static void genModOneByte (operand *left,
4217 sym_link *opetype = operandType(result);
4221 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4222 /* signed or unsigned */
4223 if (SPEC_USIGN(opetype)) {
4224 /* unsigned is easy */
4225 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4226 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4228 pic16_emitcode("div","ab");
4229 pic16_aopPut(AOP(result),"b",0);
4233 /* signed is a little bit more difficult */
4235 /* save the signs of the operands */
4236 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4239 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4240 pic16_emitcode("push","acc"); /* save it on the stack */
4242 /* now sign adjust for both left & right */
4243 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4246 lbl = newiTempLabel(NULL);
4247 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4248 pic16_emitcode("cpl","a");
4249 pic16_emitcode("inc","a");
4250 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4251 pic16_emitcode("mov","b,a");
4253 /* sign adjust left side */
4254 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4257 lbl = newiTempLabel(NULL);
4258 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4259 pic16_emitcode("cpl","a");
4260 pic16_emitcode("inc","a");
4261 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4263 /* now the multiplication */
4264 pic16_emitcode("div","ab");
4265 /* we are interested in the lower order
4267 lbl = newiTempLabel(NULL);
4268 pic16_emitcode("pop","acc");
4269 /* if there was an over flow we don't
4270 adjust the sign of the result */
4271 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4272 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4274 pic16_emitcode("clr","a");
4275 pic16_emitcode("subb","a,b");
4276 pic16_emitcode("mov","b,a");
4277 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4279 /* now we are done */
4280 pic16_aopPut(AOP(result),"b",0);
4284 /*-----------------------------------------------------------------*/
4285 /* genMod - generates code for division */
4286 /*-----------------------------------------------------------------*/
4287 static void genMod (iCode *ic)
4289 operand *left = IC_LEFT(ic);
4290 operand *right = IC_RIGHT(ic);
4291 operand *result= IC_RESULT(ic);
4293 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4294 /* assign the amsops */
4295 pic16_aopOp (left,ic,FALSE);
4296 pic16_aopOp (right,ic,FALSE);
4297 pic16_aopOp (result,ic,TRUE);
4299 /* special cases first */
4301 if (AOP_TYPE(left) == AOP_CRY &&
4302 AOP_TYPE(right)== AOP_CRY) {
4303 genModbits(left,right,result);
4307 /* if both are of size == 1 */
4308 if (AOP_SIZE(left) == 1 &&
4309 AOP_SIZE(right) == 1 ) {
4310 genModOneByte(left,right,result);
4314 /* should have been converted to function call */
4318 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4319 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4320 pic16_freeAsmop(result,NULL,ic,TRUE);
4323 /*-----------------------------------------------------------------*/
4324 /* genIfxJump :- will create a jump depending on the ifx */
4325 /*-----------------------------------------------------------------*/
4327 note: May need to add parameter to indicate when a variable is in bit space.
4329 static void genIfxJump (iCode *ic, char *jval)
4332 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4333 /* if true label then we jump if condition
4335 if ( IC_TRUE(ic) ) {
4337 if(strcmp(jval,"a") == 0)
4339 else if (strcmp(jval,"c") == 0)
4342 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4343 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4346 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4347 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4351 /* false label is present */
4352 if(strcmp(jval,"a") == 0)
4354 else if (strcmp(jval,"c") == 0)
4357 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4358 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4361 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4362 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4367 /* mark the icode as generated */
4374 /*-----------------------------------------------------------------*/
4376 /*-----------------------------------------------------------------*/
4377 static void genSkip(iCode *ifx,int status_bit)
4379 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4383 if ( IC_TRUE(ifx) ) {
4384 switch(status_bit) {
4399 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4400 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4404 switch(status_bit) {
4418 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4419 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4426 /*-----------------------------------------------------------------*/
4428 /*-----------------------------------------------------------------*/
4429 static void genSkipc(resolvedIfx *rifx)
4431 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4441 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4442 rifx->generated = 1;
4445 /*-----------------------------------------------------------------*/
4447 /*-----------------------------------------------------------------*/
4448 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4450 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4455 if( (rifx->condition ^ invert_condition) & 1)
4460 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4461 rifx->generated = 1;
4465 /*-----------------------------------------------------------------*/
4467 /*-----------------------------------------------------------------*/
4468 static void genSkipz(iCode *ifx, int condition)
4479 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4481 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4484 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4486 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4491 /*-----------------------------------------------------------------*/
4493 /*-----------------------------------------------------------------*/
4494 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4500 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4502 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4505 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4506 rifx->generated = 1;
4510 /*-----------------------------------------------------------------*/
4511 /* genChkZeroes :- greater or less than comparison */
4512 /* For each byte in a literal that is zero, inclusive or the */
4513 /* the corresponding byte in the operand with W */
4514 /* returns true if any of the bytes are zero */
4515 /*-----------------------------------------------------------------*/
4516 static int genChkZeroes(operand *op, int lit, int size)
4523 i = (lit >> (size*8)) & 0xff;
4527 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4529 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4538 /*-----------------------------------------------------------------*/
4539 /* genCmp :- greater or less than comparison */
4540 /*-----------------------------------------------------------------*/
4541 static void genCmp (operand *left,operand *right,
4542 operand *result, iCode *ifx, int sign)
4544 int size; //, offset = 0 ;
4545 unsigned long lit = 0L,i = 0;
4546 resolvedIfx rFalseIfx;
4547 // resolvedIfx rTrueIfx;
4549 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4552 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4553 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4557 resolveIfx(&rFalseIfx,ifx);
4558 truelbl = newiTempLabel(NULL);
4559 size = max(AOP_SIZE(left),AOP_SIZE(right));
4561 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4565 /* if literal is on the right then swap with left */
4566 if ((AOP_TYPE(right) == AOP_LIT)) {
4567 operand *tmp = right ;
4568 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4569 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4572 lit = (lit - 1) & mask;
4575 rFalseIfx.condition ^= 1;
4578 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4579 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4583 //if(IC_TRUE(ifx) == NULL)
4584 /* if left & right are bit variables */
4585 if (AOP_TYPE(left) == AOP_CRY &&
4586 AOP_TYPE(right) == AOP_CRY ) {
4587 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4588 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4590 /* subtract right from left if at the
4591 end the carry flag is set then we know that
4592 left is greater than right */
4594 symbol *lbl = newiTempLabel(NULL);
4597 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4598 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4602 if(AOP_TYPE(right) == AOP_LIT) {
4604 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4606 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4613 genSkipCond(&rFalseIfx,left,size-1,7);
4615 /* no need to compare to 0...*/
4616 /* NOTE: this is a de-generate compare that most certainly
4617 * creates some dead code. */
4618 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4620 if(ifx) ifx->generated = 1;
4627 //i = (lit >> (size*8)) & 0xff;
4628 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4630 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4632 i = ((0-lit) & 0xff);
4635 /* lit is 0x7f, all signed chars are less than
4636 * this except for 0x7f itself */
4637 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4638 genSkipz2(&rFalseIfx,0);
4640 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4641 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4642 genSkipc(&rFalseIfx);
4647 genSkipz2(&rFalseIfx,1);
4649 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4650 genSkipc(&rFalseIfx);
4654 if(ifx) ifx->generated = 1;
4658 /* chars are out of the way. now do ints and longs */
4661 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4668 genSkipCond(&rFalseIfx,left,size,7);
4669 if(ifx) ifx->generated = 1;
4674 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4676 //rFalseIfx.condition ^= 1;
4677 //genSkipCond(&rFalseIfx,left,size,7);
4678 //rFalseIfx.condition ^= 1;
4680 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4681 if(rFalseIfx.condition)
4682 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4684 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4686 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4687 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4688 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4691 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4693 if(rFalseIfx.condition) {
4695 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4701 genSkipc(&rFalseIfx);
4702 pic16_emitpLabel(truelbl->key);
4703 if(ifx) ifx->generated = 1;
4710 if( (lit & 0xff) == 0) {
4711 /* lower byte is zero */
4712 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4713 i = ((lit >> 8) & 0xff) ^0x80;
4714 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4715 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4716 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4717 genSkipc(&rFalseIfx);
4720 if(ifx) ifx->generated = 1;
4725 /* Special cases for signed longs */
4726 if( (lit & 0xffffff) == 0) {
4727 /* lower byte is zero */
4728 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4729 i = ((lit >> 8*3) & 0xff) ^0x80;
4730 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4731 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4732 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4733 genSkipc(&rFalseIfx);
4736 if(ifx) ifx->generated = 1;
4744 if(lit & (0x80 << (size*8))) {
4745 /* lit is negative */
4746 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4748 //genSkipCond(&rFalseIfx,left,size,7);
4750 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4752 if(rFalseIfx.condition)
4753 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4755 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4759 /* lit is positive */
4760 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4761 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4762 if(rFalseIfx.condition)
4763 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4765 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4770 This works, but is only good for ints.
4771 It also requires a "known zero" register.
4772 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4773 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4774 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
4775 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4776 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4777 genSkipc(&rFalseIfx);
4779 pic16_emitpLabel(truelbl->key);
4780 if(ifx) ifx->generated = 1;
4784 /* There are no more special cases, so perform a general compare */
4786 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4787 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4791 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4793 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4795 //rFalseIfx.condition ^= 1;
4796 genSkipc(&rFalseIfx);
4798 pic16_emitpLabel(truelbl->key);
4800 if(ifx) ifx->generated = 1;
4807 /* sign is out of the way. So now do an unsigned compare */
4808 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4811 /* General case - compare to an unsigned literal on the right.*/
4813 i = (lit >> (size*8)) & 0xff;
4814 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4815 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4817 i = (lit >> (size*8)) & 0xff;
4820 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4822 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4824 /* this byte of the lit is zero,
4825 *if it's not the last then OR in the variable */
4827 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4832 pic16_emitpLabel(lbl->key);
4833 // pic16_emitpLabel(truelbl->key);
4834 //if(emitFinalCheck)
4835 genSkipc(&rFalseIfx);
4837 pic16_emitpLabel(truelbl->key);
4839 if(ifx) ifx->generated = 1;
4846 if(AOP_TYPE(left) == AOP_LIT) {
4847 //symbol *lbl = newiTempLabel(NULL);
4849 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4852 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4855 if((lit == 0) && (sign == 0)){
4858 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4860 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4862 genSkipz2(&rFalseIfx,0);
4863 if(ifx) ifx->generated = 1;
4870 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4871 /* degenerate compare can never be true */
4872 if(rFalseIfx.condition == 0)
4873 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4875 if(ifx) ifx->generated = 1;
4880 /* signed comparisons to a literal byte */
4882 int lp1 = (lit+1) & 0xff;
4884 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4887 rFalseIfx.condition ^= 1;
4888 genSkipCond(&rFalseIfx,right,0,7);
4891 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4892 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4893 genSkipz2(&rFalseIfx,1);
4896 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4897 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4898 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4899 rFalseIfx.condition ^= 1;
4900 genSkipc(&rFalseIfx);
4904 /* unsigned comparisons to a literal byte */
4906 switch(lit & 0xff ) {
4908 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4909 genSkipz2(&rFalseIfx,0);
4912 rFalseIfx.condition ^= 1;
4913 genSkipCond(&rFalseIfx,right,0,7);
4917 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4918 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4919 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4920 rFalseIfx.condition ^= 1;
4921 if (AOP_TYPE(result) == AOP_CRY)
4922 genSkipc(&rFalseIfx);
4924 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4925 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4931 if(ifx) ifx->generated = 1;
4932 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
4938 /* Size is greater than 1 */
4946 /* this means lit = 0xffffffff, or -1 */
4949 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4950 rFalseIfx.condition ^= 1;
4951 genSkipCond(&rFalseIfx,right,size,7);
4952 if(ifx) ifx->generated = 1;
4959 if(rFalseIfx.condition) {
4960 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4961 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4964 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4966 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4970 if(rFalseIfx.condition) {
4971 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4972 pic16_emitpLabel(truelbl->key);
4974 rFalseIfx.condition ^= 1;
4975 genSkipCond(&rFalseIfx,right,s,7);
4978 if(ifx) ifx->generated = 1;
4982 if((size == 1) && (0 == (lp1&0xff))) {
4983 /* lower byte of signed word is zero */
4984 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
4985 i = ((lp1 >> 8) & 0xff) ^0x80;
4986 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4987 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4988 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4989 rFalseIfx.condition ^= 1;
4990 genSkipc(&rFalseIfx);
4993 if(ifx) ifx->generated = 1;
4997 if(lit & (0x80 << (size*8))) {
4998 /* Lit is less than zero */
4999 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5000 //rFalseIfx.condition ^= 1;
5001 //genSkipCond(&rFalseIfx,left,size,7);
5002 //rFalseIfx.condition ^= 1;
5003 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5004 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5006 if(rFalseIfx.condition)
5007 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5009 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5013 /* Lit is greater than or equal to zero */
5014 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5015 //rFalseIfx.condition ^= 1;
5016 //genSkipCond(&rFalseIfx,right,size,7);
5017 //rFalseIfx.condition ^= 1;
5019 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5020 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5022 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5023 if(rFalseIfx.condition)
5024 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5026 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5031 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5032 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5036 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5038 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5040 rFalseIfx.condition ^= 1;
5041 //rFalseIfx.condition = 1;
5042 genSkipc(&rFalseIfx);
5044 pic16_emitpLabel(truelbl->key);
5046 if(ifx) ifx->generated = 1;
5051 /* compare word or long to an unsigned literal on the right.*/
5056 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5059 break; /* handled above */
5062 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5064 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5065 genSkipz2(&rFalseIfx,0);
5069 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5071 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5074 if(rFalseIfx.condition)
5075 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5077 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5080 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5081 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5083 rFalseIfx.condition ^= 1;
5084 genSkipc(&rFalseIfx);
5087 pic16_emitpLabel(truelbl->key);
5089 if(ifx) ifx->generated = 1;
5095 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5096 i = (lit >> (size*8)) & 0xff;
5098 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5099 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5102 i = (lit >> (size*8)) & 0xff;
5105 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5107 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5109 /* this byte of the lit is zero,
5110 * if it's not the last then OR in the variable */
5112 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5117 pic16_emitpLabel(lbl->key);
5119 rFalseIfx.condition ^= 1;
5121 genSkipc(&rFalseIfx);
5125 pic16_emitpLabel(truelbl->key);
5126 if(ifx) ifx->generated = 1;
5130 /* Compare two variables */
5132 DEBUGpic16_emitcode(";sign","%d",sign);
5136 /* Sigh. thus sucks... */
5140 pctemp = pic16_popGetTempReg();
5141 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5142 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5143 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5144 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5145 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5146 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5147 pic16_popReleaseTempReg(pctemp);
5149 /* Signed char comparison */
5150 /* Special thanks to Nikolai Golovchenko for this snippet */
5151 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5152 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5153 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5154 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5155 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5156 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5158 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5159 genSkipc(&rFalseIfx);
5161 if(ifx) ifx->generated = 1;
5167 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5168 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5172 /* The rest of the bytes of a multi-byte compare */
5176 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5179 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5180 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5185 pic16_emitpLabel(lbl->key);
5187 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5188 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5189 (AOP_TYPE(result) == AOP_REG)) {
5190 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5191 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5193 genSkipc(&rFalseIfx);
5195 //genSkipc(&rFalseIfx);
5196 if(ifx) ifx->generated = 1;
5203 if ((AOP_TYPE(result) != AOP_CRY)
5204 && AOP_SIZE(result)) {
5205 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5207 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5209 pic16_outBitC(result);
5211 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5212 /* if the result is used in the next
5213 ifx conditional branch then generate
5214 code a little differently */
5216 genIfxJump (ifx,"c");
5218 pic16_outBitC(result);
5219 /* leave the result in acc */
5224 /*-----------------------------------------------------------------*/
5225 /* genCmpGt :- greater than comparison */
5226 /*-----------------------------------------------------------------*/
5227 static void genCmpGt (iCode *ic, iCode *ifx)
5229 operand *left, *right, *result;
5230 sym_link *letype , *retype;
5233 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5235 right= IC_RIGHT(ic);
5236 result = IC_RESULT(ic);
5238 letype = getSpec(operandType(left));
5239 retype =getSpec(operandType(right));
5240 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5241 /* assign the amsops */
5242 pic16_aopOp (left,ic,FALSE);
5243 pic16_aopOp (right,ic,FALSE);
5244 pic16_aopOp (result,ic,TRUE);
5246 genCmp(right, left, result, ifx, sign);
5248 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5249 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5250 pic16_freeAsmop(result,NULL,ic,TRUE);
5253 /*-----------------------------------------------------------------*/
5254 /* genCmpLt - less than comparisons */
5255 /*-----------------------------------------------------------------*/
5256 static void genCmpLt (iCode *ic, iCode *ifx)
5258 operand *left, *right, *result;
5259 sym_link *letype , *retype;
5262 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5264 right= IC_RIGHT(ic);
5265 result = IC_RESULT(ic);
5267 letype = getSpec(operandType(left));
5268 retype =getSpec(operandType(right));
5269 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5271 /* assign the amsops */
5272 pic16_aopOp (left,ic,FALSE);
5273 pic16_aopOp (right,ic,FALSE);
5274 pic16_aopOp (result,ic,TRUE);
5276 genCmp(left, right, result, ifx, sign);
5278 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5279 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5280 pic16_freeAsmop(result,NULL,ic,TRUE);
5285 // FIXME reenable literal optimisation when the pic16 port is stable
5287 /*-----------------------------------------------------------------*/
5288 /* genc16bit2lit - compare a 16 bit value to a literal */
5289 /*-----------------------------------------------------------------*/
5290 static void genc16bit2lit(operand *op, int lit, int offset)
5294 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
5295 if( (lit&0xff) == 0)
5300 switch( BYTEofLONG(lit,i)) {
5302 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5305 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5308 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5311 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5312 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5317 switch( BYTEofLONG(lit,i)) {
5319 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5323 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5327 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5330 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5332 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5341 /*-----------------------------------------------------------------*/
5342 /* gencjneshort - compare and jump if not equal */
5343 /*-----------------------------------------------------------------*/
5344 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5346 int size = max(AOP_SIZE(left),AOP_SIZE(right));
5348 int res_offset = 0; /* the result may be a different size then left or right */
5349 int res_size = AOP_SIZE(result);
5351 symbol *lbl, *lbl_done;
5353 unsigned long lit = 0L;
5354 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5356 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5357 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5359 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
5360 resolveIfx(&rIfx,ifx);
5361 lbl = newiTempLabel(NULL);
5362 lbl_done = newiTempLabel(NULL);
5365 /* if the left side is a literal or
5366 if the right is in a pointer register and left
5368 if ((AOP_TYPE(left) == AOP_LIT) ||
5369 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5374 if(AOP_TYPE(right) == AOP_LIT)
5375 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5377 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5378 preserve_result = 1;
5380 if(result && !preserve_result)
5383 for(i = 0; i < AOP_SIZE(result); i++)
5384 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5388 /* if the right side is a literal then anything goes */
5389 if (AOP_TYPE(right) == AOP_LIT &&
5390 AOP_TYPE(left) != AOP_DIR ) {
5393 genc16bit2lit(left, lit, 0);
5395 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5398 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5401 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5402 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5404 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5408 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5410 if(res_offset < res_size-1)
5418 /* if the right side is in a register or in direct space or
5419 if the left is a pointer register & right is not */
5420 else if (AOP_TYPE(right) == AOP_REG ||
5421 AOP_TYPE(right) == AOP_DIR ||
5422 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5423 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5424 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5425 int lbl_key = lbl->key;
5428 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5429 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5431 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5432 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5433 __FUNCTION__,__LINE__);
5437 /* switch(size) { */
5439 /* genc16bit2lit(left, lit, 0); */
5441 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5446 if((AOP_TYPE(left) == AOP_DIR) &&
5447 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5449 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5450 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5452 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5454 switch (lit & 0xff) {
5456 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5459 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5460 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5461 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5465 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5466 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5467 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5468 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5472 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5473 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5478 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5481 if(AOP_TYPE(result) == AOP_CRY) {
5482 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5487 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5489 /* fix me. probably need to check result size too */
5490 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5495 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5496 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5503 if(res_offset < res_size-1)
5508 } else if(AOP_TYPE(right) == AOP_REG &&
5509 AOP_TYPE(left) != AOP_DIR){
5512 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5513 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5514 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5519 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5521 if(res_offset < res_size-1)
5526 /* right is a pointer reg need both a & b */
5528 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5530 pic16_emitcode("mov","b,%s",l);
5531 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5532 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5537 if(result && preserve_result)
5540 for(i = 0; i < AOP_SIZE(result); i++)
5541 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5544 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5546 if(result && preserve_result)
5547 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5550 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5552 pic16_emitpLabel(lbl->key);
5554 if(result && preserve_result)
5557 for(i = 0; i < AOP_SIZE(result); i++)
5558 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5560 pic16_emitpLabel(lbl_done->key);
5563 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5571 /*-----------------------------------------------------------------*/
5572 /* gencjne - compare and jump if not equal */
5573 /*-----------------------------------------------------------------*/
5574 static void gencjne(operand *left, operand *right, iCode *ifx)
5576 symbol *tlbl = newiTempLabel(NULL);
5578 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5579 gencjneshort(left, right, lbl);
5581 pic16_emitcode("mov","a,%s",one);
5582 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5583 pic16_emitcode("","%05d_DS_:",lbl->key+100);
5584 pic16_emitcode("clr","a");
5585 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5587 pic16_emitpLabel(lbl->key);
5588 pic16_emitpLabel(tlbl->key);
5594 /*-----------------------------------------------------------------*/
5595 /* is_LitOp - check if operand has to be treated as literal */
5596 /*-----------------------------------------------------------------*/
5597 static bool is_LitOp(operand *op)
5599 return (AOP_TYPE(op) == AOP_LIT)
5600 || ( (AOP_TYPE(op) == AOP_PCODE)
5601 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5602 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));
5605 /*-----------------------------------------------------------------*/
5606 /* is_LitAOp - check if operand has to be treated as literal */
5607 /*-----------------------------------------------------------------*/
5608 static bool is_LitAOp(asmop *aop)
5610 return (aop->type == AOP_LIT)
5611 || ( (aop->type == AOP_PCODE)
5612 && ( (aop->aopu.pcop->type == PO_LITERAL)
5613 || (aop->aopu.pcop->type == PO_IMMEDIATE) ));
5618 /*-----------------------------------------------------------------*/
5619 /* genCmpEq - generates code for equal to */
5620 /*-----------------------------------------------------------------*/
5621 static void genCmpEq (iCode *ic, iCode *ifx)
5623 operand *left, *right, *result;
5624 symbol *falselbl = newiTempLabel(NULL);
5625 symbol *donelbl = newiTempLabel(NULL);
5627 int preserve_result = 0;
5628 int generate_result = 0;
5631 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5632 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5633 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5635 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5636 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5638 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5640 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5641 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5645 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5647 operand *tmp = right ;
5652 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5653 preserve_result = 1;
5655 if(result && AOP_SIZE(result))
5656 generate_result = 1;
5658 if(generate_result && !preserve_result)
5660 for(i = 0; i < AOP_SIZE(result); i++)
5661 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5664 for(i=0; i < AOP_SIZE(left); i++)
5666 if(AOP_TYPE(left) != AOP_ACC)
5669 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5671 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5674 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
5676 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
5678 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5683 if(generate_result && preserve_result)
5685 for(i = 0; i < AOP_SIZE(result); i++)
5686 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5690 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5692 if(generate_result && preserve_result)
5693 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5695 if(ifx && IC_TRUE(ifx))
5696 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5698 if(ifx && IC_FALSE(ifx))
5699 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5701 pic16_emitpLabel(falselbl->key);
5705 if(ifx && IC_FALSE(ifx))
5706 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5708 if(generate_result && preserve_result)
5710 for(i = 0; i < AOP_SIZE(result); i++)
5711 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5714 pic16_emitpLabel(donelbl->key);
5720 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5721 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5722 pic16_freeAsmop(result,NULL,ic,TRUE);
5728 // old version kept for reference
5730 /*-----------------------------------------------------------------*/
5731 /* genCmpEq - generates code for equal to */
5732 /*-----------------------------------------------------------------*/
5733 static void genCmpEq (iCode *ic, iCode *ifx)
5735 operand *left, *right, *result;
5736 unsigned long lit = 0L;
5738 symbol *falselbl = newiTempLabel(NULL);
5741 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5744 DEBUGpic16_emitcode ("; ifx is non-null","");
5746 DEBUGpic16_emitcode ("; ifx is null","");
5748 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5749 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5750 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5752 size = max(AOP_SIZE(left),AOP_SIZE(right));
5754 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5756 /* if literal, literal on the right or
5757 if the right is in a pointer register and left
5759 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
5760 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5761 operand *tmp = right ;
5767 if(ifx && !AOP_SIZE(result)){
5769 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
5770 /* if they are both bit variables */
5771 if (AOP_TYPE(left) == AOP_CRY &&
5772 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5773 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
5774 if(AOP_TYPE(right) == AOP_LIT){
5775 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5777 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5778 pic16_emitcode("cpl","c");
5779 } else if(lit == 1L) {
5780 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5782 pic16_emitcode("clr","c");
5784 /* AOP_TYPE(right) == AOP_CRY */
5786 symbol *lbl = newiTempLabel(NULL);
5787 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5788 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5789 pic16_emitcode("cpl","c");
5790 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5792 /* if true label then we jump if condition
5794 tlbl = newiTempLabel(NULL);
5795 if ( IC_TRUE(ifx) ) {
5796 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5797 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5799 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5800 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5802 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5805 /* left and right are both bit variables, result is carry */
5808 resolveIfx(&rIfx,ifx);
5810 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5811 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5812 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5813 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5818 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
5820 /* They're not both bit variables. Is the right a literal? */
5821 if(AOP_TYPE(right) == AOP_LIT) {
5822 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5827 switch(lit & 0xff) {
5829 if ( IC_TRUE(ifx) ) {
5830 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5832 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5834 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5835 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5839 if ( IC_TRUE(ifx) ) {
5840 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5842 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5844 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5845 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5849 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5851 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5856 /* end of size == 1 */
5860 genc16bit2lit(left,lit,offset);
5863 /* end of size == 2 */
5868 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5869 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5870 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5871 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5874 /* search for patterns that can be optimized */
5876 genc16bit2lit(left,lit,0);
5880 emitSKPZ; // if hi word unequal
5882 emitSKPNZ; // if hi word equal
5884 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5885 genc16bit2lit(left,lit,2);
5888 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5889 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5893 pic16_emitpLabel(falselbl->key);
5902 } else if(AOP_TYPE(right) == AOP_CRY ) {
5903 /* we know the left is not a bit, but that the right is */
5904 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5905 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5906 pic16_popGet(AOP(right),offset));
5907 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5909 /* if the two are equal, then W will be 0 and the Z bit is set
5910 * we could test Z now, or go ahead and check the high order bytes if
5911 * the variable we're comparing is larger than a byte. */
5914 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5916 if ( IC_TRUE(ifx) ) {
5918 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5919 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5922 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5923 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5927 /* They're both variables that are larger than bits */
5930 tlbl = newiTempLabel(NULL);
5933 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5934 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5936 if ( IC_TRUE(ifx) ) {
5940 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5942 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5943 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
5947 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5950 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5951 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5956 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5958 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5959 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5963 if(s>1 && IC_TRUE(ifx)) {
5964 pic16_emitpLabel(tlbl->key);
5965 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5969 /* mark the icode as generated */
5974 /* if they are both bit variables */
5975 if (AOP_TYPE(left) == AOP_CRY &&
5976 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5977 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
5978 if(AOP_TYPE(right) == AOP_LIT){
5979 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5981 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5982 pic16_emitcode("cpl","c");
5983 } else if(lit == 1L) {
5984 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5986 pic16_emitcode("clr","c");
5988 /* AOP_TYPE(right) == AOP_CRY */
5990 symbol *lbl = newiTempLabel(NULL);
5991 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5992 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5993 pic16_emitcode("cpl","c");
5994 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5997 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5998 pic16_outBitC(result);
6002 genIfxJump (ifx,"c");
6005 /* if the result is used in an arithmetic operation
6006 then put the result in place */
6007 pic16_outBitC(result);
6010 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
6011 gencjne(left,right,result,ifx);
6014 gencjne(left,right,newiTempLabel(NULL));
6016 if(IC_TRUE(ifx)->key)
6017 gencjne(left,right,IC_TRUE(ifx)->key);
6019 gencjne(left,right,IC_FALSE(ifx)->key);
6023 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6024 pic16_aopPut(AOP(result),"a",0);
6029 genIfxJump (ifx,"a");
6033 /* if the result is used in an arithmetic operation
6034 then put the result in place */
6036 if (AOP_TYPE(result) != AOP_CRY)
6037 pic16_outAcc(result);
6039 /* leave the result in acc */
6043 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6044 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6045 pic16_freeAsmop(result,NULL,ic,TRUE);
6049 /*-----------------------------------------------------------------*/
6050 /* ifxForOp - returns the icode containing the ifx for operand */
6051 /*-----------------------------------------------------------------*/
6052 static iCode *ifxForOp ( operand *op, iCode *ic )
6054 /* if true symbol then needs to be assigned */
6055 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6056 if (IS_TRUE_SYMOP(op))
6059 /* if this has register type condition and
6060 the next instruction is ifx with the same operand
6061 and live to of the operand is upto the ifx only then */
6063 && ic->next->op == IFX
6064 && IC_COND(ic->next)->key == op->key
6065 && OP_SYMBOL(op)->liveTo <= ic->next->seq
6067 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6072 ic->next->op == IFX &&
6073 IC_COND(ic->next)->key == op->key) {
6074 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6078 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6080 ic->next->op == IFX)
6081 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6084 ic->next->op == IFX &&
6085 IC_COND(ic->next)->key == op->key) {
6086 DEBUGpic16_emitcode ("; "," key is okay");
6087 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6088 OP_SYMBOL(op)->liveTo,
6093 /* the code below is completely untested
6094 * it just allows ulong2fs.c compile -- VR */
6097 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6098 __FILE__, __FUNCTION__, __LINE__);
6100 /* if this has register type condition and
6101 the next instruction is ifx with the same operand
6102 and live to of the operand is upto the ifx only then */
6104 ic->next->op == IFX &&
6105 IC_COND(ic->next)->key == op->key &&
6106 OP_SYMBOL(op)->liveTo <= ic->next->seq )
6110 ic->next->op == IFX &&
6111 IC_COND(ic->next)->key == op->key) {
6112 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6116 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6117 __FILE__, __FUNCTION__, __LINE__);
6119 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
6124 /*-----------------------------------------------------------------*/
6125 /* genAndOp - for && operation */
6126 /*-----------------------------------------------------------------*/
6127 static void genAndOp (iCode *ic)
6129 operand *left,*right, *result;
6132 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6133 /* note here that && operations that are in an
6134 if statement are taken away by backPatchLabels
6135 only those used in arthmetic operations remain */
6136 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6137 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6138 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6140 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6142 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6143 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6144 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6146 /* if both are bit variables */
6147 /* if (AOP_TYPE(left) == AOP_CRY && */
6148 /* AOP_TYPE(right) == AOP_CRY ) { */
6149 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6150 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6151 /* pic16_outBitC(result); */
6153 /* tlbl = newiTempLabel(NULL); */
6154 /* pic16_toBoolean(left); */
6155 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6156 /* pic16_toBoolean(right); */
6157 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6158 /* pic16_outBitAcc(result); */
6161 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6162 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6163 pic16_freeAsmop(result,NULL,ic,TRUE);
6167 /*-----------------------------------------------------------------*/
6168 /* genOrOp - for || operation */
6169 /*-----------------------------------------------------------------*/
6172 modified this code, but it doesn't appear to ever get called
6175 static void genOrOp (iCode *ic)
6177 operand *left,*right, *result;
6180 /* note here that || operations that are in an
6181 if statement are taken away by backPatchLabels
6182 only those used in arthmetic operations remain */
6183 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6184 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6185 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6186 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6188 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6190 /* if both are bit variables */
6191 if (AOP_TYPE(left) == AOP_CRY &&
6192 AOP_TYPE(right) == AOP_CRY ) {
6193 pic16_emitcode("clrc","");
6194 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6195 AOP(left)->aopu.aop_dir,
6196 AOP(left)->aopu.aop_dir);
6197 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6198 AOP(right)->aopu.aop_dir,
6199 AOP(right)->aopu.aop_dir);
6200 pic16_emitcode("setc","");
6203 tlbl = newiTempLabel(NULL);
6204 pic16_toBoolean(left);
6206 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6207 pic16_toBoolean(right);
6208 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6210 pic16_outBitAcc(result);
6213 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6214 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6215 pic16_freeAsmop(result,NULL,ic,TRUE);
6218 /*-----------------------------------------------------------------*/
6219 /* isLiteralBit - test if lit == 2^n */
6220 /*-----------------------------------------------------------------*/
6221 static int isLiteralBit(unsigned long lit)
6223 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6224 0x100L,0x200L,0x400L,0x800L,
6225 0x1000L,0x2000L,0x4000L,0x8000L,
6226 0x10000L,0x20000L,0x40000L,0x80000L,
6227 0x100000L,0x200000L,0x400000L,0x800000L,
6228 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6229 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6232 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6233 for(idx = 0; idx < 32; idx++)
6239 /*-----------------------------------------------------------------*/
6240 /* continueIfTrue - */
6241 /*-----------------------------------------------------------------*/
6242 static void continueIfTrue (iCode *ic)
6244 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6246 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6250 /*-----------------------------------------------------------------*/
6252 /*-----------------------------------------------------------------*/
6253 static void jumpIfTrue (iCode *ic)
6255 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6257 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6261 /*-----------------------------------------------------------------*/
6262 /* jmpTrueOrFalse - */
6263 /*-----------------------------------------------------------------*/
6264 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6266 // ugly but optimized by peephole
6267 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6269 symbol *nlbl = newiTempLabel(NULL);
6270 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
6271 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6272 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6273 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6276 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6277 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6282 /*-----------------------------------------------------------------*/
6283 /* genAnd - code for and */
6284 /*-----------------------------------------------------------------*/
6285 static void genAnd (iCode *ic, iCode *ifx)
6287 operand *left, *right, *result;
6289 unsigned long lit = 0L;
6294 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6295 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6296 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6297 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6299 resolveIfx(&rIfx,ifx);
6301 /* if left is a literal & right is not then exchange them */
6302 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6303 AOP_NEEDSACC(left)) {
6304 operand *tmp = right ;
6309 /* if result = right then exchange them */
6310 if(pic16_sameRegs(AOP(result),AOP(right))){
6311 operand *tmp = right ;
6316 /* if right is bit then exchange them */
6317 if (AOP_TYPE(right) == AOP_CRY &&
6318 AOP_TYPE(left) != AOP_CRY){
6319 operand *tmp = right ;
6323 if(AOP_TYPE(right) == AOP_LIT)
6324 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6326 size = AOP_SIZE(result);
6328 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6331 // result = bit & yy;
6332 if (AOP_TYPE(left) == AOP_CRY){
6333 // c = bit & literal;
6334 if(AOP_TYPE(right) == AOP_LIT){
6336 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6339 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6342 if(size && (AOP_TYPE(result) == AOP_CRY)){
6343 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6346 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6350 pic16_emitcode("clr","c");
6353 if (AOP_TYPE(right) == AOP_CRY){
6355 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6356 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6359 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6361 pic16_emitcode("rrc","a");
6362 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6368 pic16_outBitC(result);
6370 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6371 genIfxJump(ifx, "c");
6375 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6376 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6377 if((AOP_TYPE(right) == AOP_LIT) &&
6378 (AOP_TYPE(result) == AOP_CRY) &&
6379 (AOP_TYPE(left) != AOP_CRY)){
6380 int posbit = isLiteralBit(lit);
6384 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6387 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6393 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6394 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6396 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6397 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6400 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6401 size = AOP_SIZE(left);
6404 int bp = posbit, ofs=0;
6411 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6412 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
6416 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6417 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6419 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6426 symbol *tlbl = newiTempLabel(NULL);
6427 int sizel = AOP_SIZE(left);
6429 pic16_emitcode("setb","c");
6431 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6432 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6434 if((posbit = isLiteralBit(bytelit)) != 0)
6435 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6437 if(bytelit != 0x0FFL)
6438 pic16_emitcode("anl","a,%s",
6439 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6440 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6445 // bit = left & literal
6447 pic16_emitcode("clr","c");
6448 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6450 // if(left & literal)
6453 jmpTrueOrFalse(ifx, tlbl);
6457 pic16_outBitC(result);
6461 /* if left is same as result */
6462 if(pic16_sameRegs(AOP(result),AOP(left))){
6464 for(;size--; offset++,lit>>=8) {
6465 if(AOP_TYPE(right) == AOP_LIT){
6466 switch(lit & 0xff) {
6468 /* and'ing with 0 has clears the result */
6469 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6470 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6473 /* and'ing with 0xff is a nop when the result and left are the same */
6478 int p = my_powof2( (~lit) & 0xff );
6480 /* only one bit is set in the literal, so use a bcf instruction */
6481 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6482 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6485 pic16_emitcode("movlw","0x%x", (lit & 0xff));
6486 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6487 if(know_W != (lit&0xff))
6488 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6490 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6495 if (AOP_TYPE(left) == AOP_ACC) {
6496 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6498 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6499 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6506 // left & result in different registers
6507 if(AOP_TYPE(result) == AOP_CRY){
6509 // if(size), result in bit
6510 // if(!size && ifx), conditional oper: if(left & right)
6511 symbol *tlbl = newiTempLabel(NULL);
6512 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6514 pic16_emitcode("setb","c");
6516 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6517 pic16_emitcode("anl","a,%s",
6518 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6519 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6524 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6525 pic16_outBitC(result);
6527 jmpTrueOrFalse(ifx, tlbl);
6529 for(;(size--);offset++) {
6531 // result = left & right
6532 if(AOP_TYPE(right) == AOP_LIT){
6533 int t = (lit >> (offset*8)) & 0x0FFL;
6536 pic16_emitcode("clrf","%s",
6537 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6538 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6541 pic16_emitcode("movf","%s,w",
6542 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6543 pic16_emitcode("movwf","%s",
6544 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6545 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6546 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6549 pic16_emitcode("movlw","0x%x",t);
6550 pic16_emitcode("andwf","%s,w",
6551 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6552 pic16_emitcode("movwf","%s",
6553 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6555 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6556 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6557 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6562 if (AOP_TYPE(left) == AOP_ACC) {
6563 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6564 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6566 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6567 pic16_emitcode("andwf","%s,w",
6568 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6569 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6570 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6572 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6573 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6579 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6580 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6581 pic16_freeAsmop(result,NULL,ic,TRUE);
6584 /*-----------------------------------------------------------------*/
6585 /* genOr - code for or */
6586 /*-----------------------------------------------------------------*/
6587 static void genOr (iCode *ic, iCode *ifx)
6589 operand *left, *right, *result;
6591 unsigned long lit = 0L;
6593 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6595 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6596 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6597 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6599 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6601 /* if left is a literal & right is not then exchange them */
6602 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6603 AOP_NEEDSACC(left)) {
6604 operand *tmp = right ;
6609 /* if result = right then exchange them */
6610 if(pic16_sameRegs(AOP(result),AOP(right))){
6611 operand *tmp = right ;
6616 /* if right is bit then exchange them */
6617 if (AOP_TYPE(right) == AOP_CRY &&
6618 AOP_TYPE(left) != AOP_CRY){
6619 operand *tmp = right ;
6624 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6626 if(AOP_TYPE(right) == AOP_LIT)
6627 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6629 size = AOP_SIZE(result);
6633 if (AOP_TYPE(left) == AOP_CRY){
6634 if(AOP_TYPE(right) == AOP_LIT){
6635 // c = bit & literal;
6637 // lit != 0 => result = 1
6638 if(AOP_TYPE(result) == AOP_CRY){
6640 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6641 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6642 // AOP(result)->aopu.aop_dir,
6643 // AOP(result)->aopu.aop_dir);
6645 continueIfTrue(ifx);
6649 // lit == 0 => result = left
6650 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6652 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6655 if (AOP_TYPE(right) == AOP_CRY){
6656 if(pic16_sameRegs(AOP(result),AOP(left))){
6658 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6659 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6660 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6662 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6663 AOP(result)->aopu.aop_dir,
6664 AOP(result)->aopu.aop_dir);
6665 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6666 AOP(right)->aopu.aop_dir,
6667 AOP(right)->aopu.aop_dir);
6668 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6669 AOP(result)->aopu.aop_dir,
6670 AOP(result)->aopu.aop_dir);
6672 if( AOP_TYPE(result) == AOP_ACC) {
6673 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6674 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6675 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6676 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6680 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6681 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6682 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6683 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6685 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6686 AOP(result)->aopu.aop_dir,
6687 AOP(result)->aopu.aop_dir);
6688 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6689 AOP(right)->aopu.aop_dir,
6690 AOP(right)->aopu.aop_dir);
6691 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6692 AOP(left)->aopu.aop_dir,
6693 AOP(left)->aopu.aop_dir);
6694 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6695 AOP(result)->aopu.aop_dir,
6696 AOP(result)->aopu.aop_dir);
6701 symbol *tlbl = newiTempLabel(NULL);
6702 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6705 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6706 if( AOP_TYPE(right) == AOP_ACC) {
6707 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6709 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6710 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6715 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6716 pic16_emitcode(";XXX setb","c");
6717 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6718 AOP(left)->aopu.aop_dir,tlbl->key+100);
6719 pic16_toBoolean(right);
6720 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6721 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6722 jmpTrueOrFalse(ifx, tlbl);
6726 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6733 pic16_outBitC(result);
6735 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6736 genIfxJump(ifx, "c");
6740 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6741 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6742 if((AOP_TYPE(right) == AOP_LIT) &&
6743 (AOP_TYPE(result) == AOP_CRY) &&
6744 (AOP_TYPE(left) != AOP_CRY)){
6746 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6749 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6751 continueIfTrue(ifx);
6754 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6755 // lit = 0, result = boolean(left)
6757 pic16_emitcode(";XXX setb","c");
6758 pic16_toBoolean(right);
6760 symbol *tlbl = newiTempLabel(NULL);
6761 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6763 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6765 genIfxJump (ifx,"a");
6769 pic16_outBitC(result);
6773 /* if left is same as result */
6774 if(pic16_sameRegs(AOP(result),AOP(left))){
6776 for(;size--; offset++,lit>>=8) {
6777 if(AOP_TYPE(right) == AOP_LIT){
6778 if((lit & 0xff) == 0)
6779 /* or'ing with 0 has no effect */
6782 int p = my_powof2(lit & 0xff);
6784 /* only one bit is set in the literal, so use a bsf instruction */
6785 pic16_emitpcode(POC_BSF,
6786 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6788 if(know_W != (lit & 0xff))
6789 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6790 know_W = lit & 0xff;
6791 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6796 if (AOP_TYPE(left) == AOP_ACC) {
6797 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
6798 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6800 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6801 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6803 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6804 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6810 // left & result in different registers
6811 if(AOP_TYPE(result) == AOP_CRY){
6813 // if(size), result in bit
6814 // if(!size && ifx), conditional oper: if(left | right)
6815 symbol *tlbl = newiTempLabel(NULL);
6816 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6817 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6821 pic16_emitcode(";XXX setb","c");
6823 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6824 pic16_emitcode(";XXX orl","a,%s",
6825 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6826 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6831 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6832 pic16_outBitC(result);
6834 jmpTrueOrFalse(ifx, tlbl);
6835 } else for(;(size--);offset++){
6837 // result = left & right
6838 if(AOP_TYPE(right) == AOP_LIT){
6839 int t = (lit >> (offset*8)) & 0x0FFL;
6842 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
6843 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6845 pic16_emitcode("movf","%s,w",
6846 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6847 pic16_emitcode("movwf","%s",
6848 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6851 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6852 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6853 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6855 pic16_emitcode("movlw","0x%x",t);
6856 pic16_emitcode("iorwf","%s,w",
6857 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6858 pic16_emitcode("movwf","%s",
6859 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6865 // faster than result <- left, anl result,right
6866 // and better if result is SFR
6867 if (AOP_TYPE(left) == AOP_ACC) {
6868 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
6869 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6871 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6872 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
6874 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6875 pic16_emitcode("iorwf","%s,w",
6876 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6878 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6879 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6884 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6885 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6886 pic16_freeAsmop(result,NULL,ic,TRUE);
6889 /*-----------------------------------------------------------------*/
6890 /* genXor - code for xclusive or */
6891 /*-----------------------------------------------------------------*/
6892 static void genXor (iCode *ic, iCode *ifx)
6894 operand *left, *right, *result;
6896 unsigned long lit = 0L;
6898 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6900 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6901 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6902 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6904 /* if left is a literal & right is not ||
6905 if left needs acc & right does not */
6906 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6907 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6908 operand *tmp = right ;
6913 /* if result = right then exchange them */
6914 if(pic16_sameRegs(AOP(result),AOP(right))){
6915 operand *tmp = right ;
6920 /* if right is bit then exchange them */
6921 if (AOP_TYPE(right) == AOP_CRY &&
6922 AOP_TYPE(left) != AOP_CRY){
6923 operand *tmp = right ;
6927 if(AOP_TYPE(right) == AOP_LIT)
6928 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6930 size = AOP_SIZE(result);
6934 if (AOP_TYPE(left) == AOP_CRY){
6935 if(AOP_TYPE(right) == AOP_LIT){
6936 // c = bit & literal;
6938 // lit>>1 != 0 => result = 1
6939 if(AOP_TYPE(result) == AOP_CRY){
6941 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
6942 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6944 continueIfTrue(ifx);
6947 pic16_emitcode("setb","c");
6951 // lit == 0, result = left
6952 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6954 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6956 // lit == 1, result = not(left)
6957 if(size && pic16_sameRegs(AOP(result),AOP(left))){
6958 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
6959 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
6960 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6963 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6964 pic16_emitcode("cpl","c");
6971 symbol *tlbl = newiTempLabel(NULL);
6972 if (AOP_TYPE(right) == AOP_CRY){
6974 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6977 int sizer = AOP_SIZE(right);
6979 // if val>>1 != 0, result = 1
6980 pic16_emitcode("setb","c");
6982 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6984 // test the msb of the lsb
6985 pic16_emitcode("anl","a,#0xfe");
6986 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6990 pic16_emitcode("rrc","a");
6992 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6993 pic16_emitcode("cpl","c");
6994 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6999 pic16_outBitC(result);
7001 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7002 genIfxJump(ifx, "c");
7006 if(pic16_sameRegs(AOP(result),AOP(left))){
7007 /* if left is same as result */
7008 for(;size--; offset++) {
7009 if(AOP_TYPE(right) == AOP_LIT){
7010 int t = (lit >> (offset*8)) & 0x0FFL;
7014 if (IS_AOP_PREG(left)) {
7015 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7016 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7017 pic16_aopPut(AOP(result),"a",offset);
7019 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7020 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7021 pic16_emitcode("xrl","%s,%s",
7022 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7023 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7026 if (AOP_TYPE(left) == AOP_ACC)
7027 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7029 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7030 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7032 if (IS_AOP_PREG(left)) {
7033 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7034 pic16_aopPut(AOP(result),"a",offset);
7036 pic16_emitcode("xrl","%s,a",
7037 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7043 // left & result in different registers
7044 if(AOP_TYPE(result) == AOP_CRY){
7046 // if(size), result in bit
7047 // if(!size && ifx), conditional oper: if(left ^ right)
7048 symbol *tlbl = newiTempLabel(NULL);
7049 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7051 pic16_emitcode("setb","c");
7053 if((AOP_TYPE(right) == AOP_LIT) &&
7054 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7055 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7057 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7058 pic16_emitcode("xrl","a,%s",
7059 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7061 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7066 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7067 pic16_outBitC(result);
7069 jmpTrueOrFalse(ifx, tlbl);
7070 } else for(;(size--);offset++){
7072 // result = left & right
7073 if(AOP_TYPE(right) == AOP_LIT){
7074 int t = (lit >> (offset*8)) & 0x0FFL;
7077 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7078 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7079 pic16_emitcode("movf","%s,w",
7080 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7081 pic16_emitcode("movwf","%s",
7082 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7085 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7086 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7087 pic16_emitcode("comf","%s,w",
7088 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7089 pic16_emitcode("movwf","%s",
7090 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7093 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7094 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7095 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7096 pic16_emitcode("movlw","0x%x",t);
7097 pic16_emitcode("xorwf","%s,w",
7098 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7099 pic16_emitcode("movwf","%s",
7100 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7106 // faster than result <- left, anl result,right
7107 // and better if result is SFR
7108 if (AOP_TYPE(left) == AOP_ACC) {
7109 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7110 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7112 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7113 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7114 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7115 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7117 if ( AOP_TYPE(result) != AOP_ACC){
7118 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7119 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7125 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7126 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7127 pic16_freeAsmop(result,NULL,ic,TRUE);
7130 /*-----------------------------------------------------------------*/
7131 /* genInline - write the inline code out */
7132 /*-----------------------------------------------------------------*/
7133 static void genInline (iCode *ic)
7135 char *buffer, *bp, *bp1;
7137 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7139 _G.inLine += (!options.asmpeep);
7141 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7142 strcpy(buffer,IC_INLINE(ic));
7144 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7146 /* emit each line as a code */
7152 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7160 /* print label, use this special format with NULL directive
7161 * to denote that the argument should not be indented with tab */
7162 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7169 if ((bp1 != bp) && *bp1)
7170 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7175 _G.inLine -= (!options.asmpeep);
7178 /*-----------------------------------------------------------------*/
7179 /* genRRC - rotate right with carry */
7180 /*-----------------------------------------------------------------*/
7181 static void genRRC (iCode *ic)
7183 operand *left , *result ;
7184 int size, offset = 0, same;
7186 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7188 /* rotate right with carry */
7190 result=IC_RESULT(ic);
7191 pic16_aopOp (left,ic,FALSE);
7192 pic16_aopOp (result,ic,FALSE);
7194 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7196 same = pic16_sameRegs(AOP(result),AOP(left));
7198 size = AOP_SIZE(result);
7200 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7202 /* get the lsb and put it into the carry */
7203 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7210 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7212 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7213 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7219 pic16_freeAsmop(left,NULL,ic,TRUE);
7220 pic16_freeAsmop(result,NULL,ic,TRUE);
7223 /*-----------------------------------------------------------------*/
7224 /* genRLC - generate code for rotate left with carry */
7225 /*-----------------------------------------------------------------*/
7226 static void genRLC (iCode *ic)
7228 operand *left , *result ;
7229 int size, offset = 0;
7232 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7233 /* rotate right with carry */
7235 result=IC_RESULT(ic);
7236 pic16_aopOp (left,ic,FALSE);
7237 pic16_aopOp (result,ic,FALSE);
7239 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7241 same = pic16_sameRegs(AOP(result),AOP(left));
7243 /* move it to the result */
7244 size = AOP_SIZE(result);
7246 /* get the msb and put it into the carry */
7247 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7254 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7256 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7257 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7264 pic16_freeAsmop(left,NULL,ic,TRUE);
7265 pic16_freeAsmop(result,NULL,ic,TRUE);
7269 /* gpasm can get the highest order bit with HIGH/UPPER
7270 * so the following probably is not needed -- VR */
7272 /*-----------------------------------------------------------------*/
7273 /* genGetHbit - generates code get highest order bit */
7274 /*-----------------------------------------------------------------*/
7275 static void genGetHbit (iCode *ic)
7277 operand *left, *result;
7279 result=IC_RESULT(ic);
7280 pic16_aopOp (left,ic,FALSE);
7281 pic16_aopOp (result,ic,FALSE);
7283 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7284 /* get the highest order byte into a */
7285 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7286 if(AOP_TYPE(result) == AOP_CRY){
7287 pic16_emitcode("rlc","a");
7288 pic16_outBitC(result);
7291 pic16_emitcode("rl","a");
7292 pic16_emitcode("anl","a,#0x01");
7293 pic16_outAcc(result);
7297 pic16_freeAsmop(left,NULL,ic,TRUE);
7298 pic16_freeAsmop(result,NULL,ic,TRUE);
7302 /*-----------------------------------------------------------------*/
7303 /* AccRol - rotate left accumulator by known count */
7304 /*-----------------------------------------------------------------*/
7305 static void AccRol (int shCount)
7307 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7308 shCount &= 0x0007; // shCount : 0..7
7313 pic16_emitcode("rl","a");
7316 pic16_emitcode("rl","a");
7317 pic16_emitcode("rl","a");
7320 pic16_emitcode("swap","a");
7321 pic16_emitcode("rr","a");
7324 pic16_emitcode("swap","a");
7327 pic16_emitcode("swap","a");
7328 pic16_emitcode("rl","a");
7331 pic16_emitcode("rr","a");
7332 pic16_emitcode("rr","a");
7335 pic16_emitcode("rr","a");
7341 /*-----------------------------------------------------------------*/
7342 /* AccLsh - left shift accumulator by known count */
7343 /*-----------------------------------------------------------------*/
7344 static void AccLsh (int shCount)
7346 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7352 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7355 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7356 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7359 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7360 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7363 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7366 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7367 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7370 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7371 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7374 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7378 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7381 /*-----------------------------------------------------------------*/
7382 /* AccRsh - right shift accumulator by known count */
7383 /*-----------------------------------------------------------------*/
7384 static void AccRsh (int shCount, int andmask)
7386 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7391 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7392 // andmask = 0; /* no need */
7395 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7396 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7397 // andmask = 0; /* no need */
7400 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7401 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7404 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7407 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7408 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7411 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7412 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7415 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7420 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7422 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7426 /*-----------------------------------------------------------------*/
7427 /* AccSRsh - signed right shift accumulator by known count */
7428 /*-----------------------------------------------------------------*/
7429 static void AccSRsh (int shCount)
7432 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7435 pic16_emitcode("mov","c,acc.7");
7436 pic16_emitcode("rrc","a");
7437 } else if(shCount == 2){
7438 pic16_emitcode("mov","c,acc.7");
7439 pic16_emitcode("rrc","a");
7440 pic16_emitcode("mov","c,acc.7");
7441 pic16_emitcode("rrc","a");
7443 tlbl = newiTempLabel(NULL);
7444 /* rotate right accumulator */
7445 AccRol(8 - shCount);
7446 /* and kill the higher order bits */
7447 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7448 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7449 pic16_emitcode("orl","a,#0x%02x",
7450 (unsigned char)~SRMask[shCount]);
7451 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7456 /*-----------------------------------------------------------------*/
7457 /* shiftR1Left2Result - shift right one byte from left to result */
7458 /*-----------------------------------------------------------------*/
7459 static void shiftR1Left2ResultSigned (operand *left, int offl,
7460 operand *result, int offr,
7465 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7467 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7471 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7473 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7475 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7476 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7482 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7484 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7486 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7487 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7489 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7490 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7496 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7498 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7499 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7502 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7503 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7504 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7506 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7507 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7509 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7513 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7514 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7515 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7516 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
7517 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7521 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7523 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7524 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7526 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7527 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
7528 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7529 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
7530 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7535 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7536 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7537 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7538 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7539 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7540 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7542 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7543 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7544 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7545 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7546 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7552 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7553 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7554 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7555 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7557 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7558 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7559 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7567 /*-----------------------------------------------------------------*/
7568 /* shiftR1Left2Result - shift right one byte from left to result */
7569 /*-----------------------------------------------------------------*/
7570 static void shiftR1Left2Result (operand *left, int offl,
7571 operand *result, int offr,
7572 int shCount, int sign)
7576 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7578 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7580 /* Copy the msb into the carry if signed. */
7582 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
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));
7601 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7603 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7604 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7607 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7612 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7614 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7615 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7618 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7619 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7620 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7621 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7625 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7626 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7627 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7631 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7632 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7633 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7635 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7640 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7641 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7642 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7643 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7644 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7649 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7650 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7651 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7660 /*-----------------------------------------------------------------*/
7661 /* shiftL1Left2Result - shift left one byte from left to result */
7662 /*-----------------------------------------------------------------*/
7663 static void shiftL1Left2Result (operand *left, int offl,
7664 operand *result, int offr, int shCount)
7669 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7671 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7672 DEBUGpic16_emitcode ("; ***","same = %d",same);
7673 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7675 /* shift left accumulator */
7676 //AccLsh(shCount); // don't comment out just yet...
7677 // pic16_aopPut(AOP(result),"a",offr);
7681 /* Shift left 1 bit position */
7682 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7684 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7686 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7687 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7691 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7692 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7693 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7694 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7697 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7698 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7699 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7700 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7701 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7704 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7705 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7706 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7709 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7710 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7711 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7712 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7715 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7716 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7717 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7718 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7719 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7722 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7723 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7724 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7728 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7733 /*-----------------------------------------------------------------*/
7734 /* movLeft2Result - move byte from left to result */
7735 /*-----------------------------------------------------------------*/
7736 static void movLeft2Result (operand *left, int offl,
7737 operand *result, int offr)
7740 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7741 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7742 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7744 if (*l == '@' && (IS_AOP_PREG(result))) {
7745 pic16_emitcode("mov","a,%s",l);
7746 pic16_aopPut(AOP(result),"a",offr);
7748 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7749 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7754 /*-----------------------------------------------------------------*/
7755 /* shiftL2Left2Result - shift left two bytes from left to result */
7756 /*-----------------------------------------------------------------*/
7757 static void shiftL2Left2Result (operand *left, int offl,
7758 operand *result, int offr, int shCount)
7760 int same = pic16_sameRegs(AOP(result), AOP(left));
7763 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7765 if (same && (offl != offr)) { // shift bytes
7768 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7769 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7771 } else { // just treat as different later on
7784 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7785 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7786 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7790 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7791 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7797 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7798 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7799 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7800 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7801 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7802 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7803 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7805 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7806 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7810 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7811 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7812 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7813 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7814 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7815 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7816 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7817 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7818 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7819 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7822 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7823 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7824 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7825 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7826 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7836 /* note, use a mov/add for the shift since the mov has a
7837 chance of getting optimized out */
7838 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7839 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7840 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7841 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7842 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7846 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7847 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7853 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7854 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7855 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7856 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7857 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7858 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7859 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7860 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7864 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7865 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7869 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7870 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7871 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7872 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7874 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7875 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7876 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7877 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7878 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7879 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7880 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7881 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7884 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7885 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7886 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7887 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7888 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7893 /*-----------------------------------------------------------------*/
7894 /* shiftR2Left2Result - shift right two bytes from left to result */
7895 /*-----------------------------------------------------------------*/
7896 static void shiftR2Left2Result (operand *left, int offl,
7897 operand *result, int offr,
7898 int shCount, int sign)
7900 int same = pic16_sameRegs(AOP(result), AOP(left));
7902 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7904 if (same && (offl != offr)) { // shift right bytes
7907 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7908 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7910 } else { // just treat as different later on
7922 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7927 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7928 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7930 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7931 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7932 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7933 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7938 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7941 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7942 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7949 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7950 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7951 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7953 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7954 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7955 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7956 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7958 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7959 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7960 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7962 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7963 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7964 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7965 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7966 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7970 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7971 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7975 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7976 pic16_emitpcode(POC_BTFSC,
7977 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
7978 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7986 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7987 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7989 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7990 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7991 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7992 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7994 pic16_emitpcode(POC_BTFSC,
7995 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0, PO_GPR_REGISTER));
7996 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7998 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7999 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8000 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8001 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8003 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8004 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8005 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8006 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8007 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8008 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8009 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8010 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8012 pic16_emitpcode(POC_BTFSC,
8013 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8014 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8016 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8017 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8024 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8025 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8026 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8027 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8030 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8032 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8037 /*-----------------------------------------------------------------*/
8038 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8039 /*-----------------------------------------------------------------*/
8040 static void shiftLLeftOrResult (operand *left, int offl,
8041 operand *result, int offr, int shCount)
8043 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8045 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8046 /* shift left accumulator */
8048 /* or with result */
8049 /* back to result */
8050 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8053 /*-----------------------------------------------------------------*/
8054 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8055 /*-----------------------------------------------------------------*/
8056 static void shiftRLeftOrResult (operand *left, int offl,
8057 operand *result, int offr, int shCount)
8059 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8061 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8062 /* shift right accumulator */
8064 /* or with result */
8065 /* back to result */
8066 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8069 /*-----------------------------------------------------------------*/
8070 /* genlshOne - left shift a one byte quantity by known count */
8071 /*-----------------------------------------------------------------*/
8072 static void genlshOne (operand *result, operand *left, int shCount)
8074 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8075 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8078 /*-----------------------------------------------------------------*/
8079 /* genlshTwo - left shift two bytes by known amount != 0 */
8080 /*-----------------------------------------------------------------*/
8081 static void genlshTwo (operand *result,operand *left, int shCount)
8085 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8086 size = pic16_getDataSize(result);
8088 /* if shCount >= 8 */
8094 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8096 movLeft2Result(left, LSB, result, MSB16);
8098 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8101 /* 1 <= shCount <= 7 */
8104 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8106 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8110 /*-----------------------------------------------------------------*/
8111 /* shiftLLong - shift left one long from left to result */
8112 /* offr = LSB or MSB16 */
8113 /*-----------------------------------------------------------------*/
8114 static void shiftLLong (operand *left, operand *result, int offr )
8116 int size = AOP_SIZE(result);
8117 int same = pic16_sameRegs(AOP(left),AOP(result));
8120 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8122 if (same && (offr == MSB16)) { //shift one byte
8123 for(i=size-1;i>=MSB16;i--) {
8124 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8125 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8128 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8131 if (size >= LSB+offr ){
8133 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8135 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8136 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8140 if(size >= MSB16+offr){
8142 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8144 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8145 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8149 if(size >= MSB24+offr){
8151 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8153 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8154 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8158 if(size > MSB32+offr){
8160 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8162 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8163 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8167 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8171 /*-----------------------------------------------------------------*/
8172 /* genlshFour - shift four byte by a known amount != 0 */
8173 /*-----------------------------------------------------------------*/
8174 static void genlshFour (operand *result, operand *left, int shCount)
8178 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8179 size = AOP_SIZE(result);
8181 /* if shifting more that 3 bytes */
8182 if (shCount >= 24 ) {
8185 /* lowest order of left goes to the highest
8186 order of the destination */
8187 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8189 movLeft2Result(left, LSB, result, MSB32);
8191 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8192 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8193 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8198 /* more than two bytes */
8199 else if ( shCount >= 16 ) {
8200 /* lower order two bytes goes to higher order two bytes */
8202 /* if some more remaining */
8204 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8206 movLeft2Result(left, MSB16, result, MSB32);
8207 movLeft2Result(left, LSB, result, MSB24);
8209 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8210 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8214 /* if more than 1 byte */
8215 else if ( shCount >= 8 ) {
8216 /* lower order three bytes goes to higher order three bytes */
8220 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8222 movLeft2Result(left, LSB, result, MSB16);
8224 else{ /* size = 4 */
8226 movLeft2Result(left, MSB24, result, MSB32);
8227 movLeft2Result(left, MSB16, result, MSB24);
8228 movLeft2Result(left, LSB, result, MSB16);
8229 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8231 else if(shCount == 1)
8232 shiftLLong(left, result, MSB16);
8234 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8235 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8236 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8237 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8242 /* 1 <= shCount <= 7 */
8243 else if(shCount <= 3)
8245 shiftLLong(left, result, LSB);
8246 while(--shCount >= 1)
8247 shiftLLong(result, result, LSB);
8249 /* 3 <= shCount <= 7, optimize */
8251 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8252 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8253 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8257 /*-----------------------------------------------------------------*/
8258 /* genLeftShiftLiteral - left shifting by known count */
8259 /*-----------------------------------------------------------------*/
8260 static void genLeftShiftLiteral (operand *left,
8265 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8268 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8269 pic16_freeAsmop(right,NULL,ic,TRUE);
8271 pic16_aopOp(left,ic,FALSE);
8272 pic16_aopOp(result,ic,FALSE);
8274 size = getSize(operandType(result));
8277 pic16_emitcode("; shift left ","result %d, left %d",size,
8281 /* I suppose that the left size >= result size */
8284 movLeft2Result(left, size, result, size);
8288 else if(shCount >= (size * 8))
8290 pic16_aopPut(AOP(result),zero,size);
8294 genlshOne (result,left,shCount);
8299 genlshTwo (result,left,shCount);
8303 genlshFour (result,left,shCount);
8307 pic16_freeAsmop(left,NULL,ic,TRUE);
8308 pic16_freeAsmop(result,NULL,ic,TRUE);
8311 /*-----------------------------------------------------------------*
8312 * genMultiAsm - repeat assembly instruction for size of register.
8313 * if endian == 1, then the high byte (i.e base address + size of
8314 * register) is used first else the low byte is used first;
8315 *-----------------------------------------------------------------*/
8316 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8321 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8334 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
8339 /*-----------------------------------------------------------------*/
8340 /* genLeftShift - generates code for left shifting */
8341 /*-----------------------------------------------------------------*/
8342 static void genLeftShift (iCode *ic)
8344 operand *left,*right, *result;
8347 symbol *tlbl , *tlbl1;
8350 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8352 right = IC_RIGHT(ic);
8354 result = IC_RESULT(ic);
8356 pic16_aopOp(right,ic,FALSE);
8358 /* if the shift count is known then do it
8359 as efficiently as possible */
8360 if (AOP_TYPE(right) == AOP_LIT) {
8361 genLeftShiftLiteral (left,right,result,ic);
8365 /* shift count is unknown then we have to form
8366 a loop get the loop count in B : Note: we take
8367 only the lower order byte since shifting
8368 more that 32 bits make no sense anyway, ( the
8369 largest size of an object can be only 32 bits ) */
8372 pic16_aopOp(left,ic,FALSE);
8373 pic16_aopOp(result,ic,FALSE);
8375 /* now move the left to the result if they are not the
8377 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8378 AOP_SIZE(result) > 1) {
8380 size = AOP_SIZE(result);
8383 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8384 if (*l == '@' && (IS_AOP_PREG(result))) {
8386 pic16_emitcode("mov","a,%s",l);
8387 pic16_aopPut(AOP(result),"a",offset);
8389 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8390 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8391 //pic16_aopPut(AOP(result),l,offset);
8397 size = AOP_SIZE(result);
8399 /* if it is only one byte then */
8401 if(optimized_for_speed) {
8402 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8403 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8404 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8405 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8406 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8407 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8408 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8409 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
8410 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
8411 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
8412 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8413 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8416 tlbl = newiTempLabel(NULL);
8417 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8418 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8419 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8422 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8423 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8424 pic16_emitpLabel(tlbl->key);
8425 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8426 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8428 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8433 if (pic16_sameRegs(AOP(left),AOP(result))) {
8435 tlbl = newiTempLabel(NULL);
8436 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8437 genMultiAsm(POC_RRCF, result, size,1);
8438 pic16_emitpLabel(tlbl->key);
8439 genMultiAsm(POC_RLCF, result, size,0);
8440 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8442 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8446 //tlbl = newiTempLabel(NULL);
8448 //tlbl1 = newiTempLabel(NULL);
8450 //reAdjustPreg(AOP(result));
8452 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8453 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8454 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8456 //pic16_emitcode("add","a,acc");
8457 //pic16_aopPut(AOP(result),"a",offset++);
8459 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8461 // pic16_emitcode("rlc","a");
8462 // pic16_aopPut(AOP(result),"a",offset++);
8464 //reAdjustPreg(AOP(result));
8466 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8467 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8470 tlbl = newiTempLabel(NULL);
8471 tlbl1= newiTempLabel(NULL);
8473 size = AOP_SIZE(result);
8476 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8478 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8480 /* offset should be 0, 1 or 3 */
8482 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8484 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8486 pic16_emitpcode(POC_MOVWF, pctemp);
8489 pic16_emitpLabel(tlbl->key);
8492 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8494 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
8496 pic16_emitpcode(POC_DECFSZ, pctemp);
8497 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8498 pic16_emitpLabel(tlbl1->key);
8500 pic16_popReleaseTempReg(pctemp);
8504 pic16_freeAsmop (right,NULL,ic,TRUE);
8505 pic16_freeAsmop(left,NULL,ic,TRUE);
8506 pic16_freeAsmop(result,NULL,ic,TRUE);
8509 /*-----------------------------------------------------------------*/
8510 /* genrshOne - right shift a one byte quantity by known count */
8511 /*-----------------------------------------------------------------*/
8512 static void genrshOne (operand *result, operand *left,
8513 int shCount, int sign)
8515 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8516 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8519 /*-----------------------------------------------------------------*/
8520 /* genrshTwo - right shift two bytes by known amount != 0 */
8521 /*-----------------------------------------------------------------*/
8522 static void genrshTwo (operand *result,operand *left,
8523 int shCount, int sign)
8525 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8526 /* if shCount >= 8 */
8530 shiftR1Left2Result(left, MSB16, result, LSB,
8533 movLeft2Result(left, MSB16, result, LSB);
8535 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8538 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8539 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8543 /* 1 <= shCount <= 7 */
8545 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
8548 /*-----------------------------------------------------------------*/
8549 /* shiftRLong - shift right one long from left to result */
8550 /* offl = LSB or MSB16 */
8551 /*-----------------------------------------------------------------*/
8552 static void shiftRLong (operand *left, int offl,
8553 operand *result, int sign)
8555 int size = AOP_SIZE(result);
8556 int same = pic16_sameRegs(AOP(left),AOP(result));
8558 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8560 if (same && (offl == MSB16)) { //shift one byte right
8561 for(i=MSB16;i<size;i++) {
8562 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8563 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8568 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8574 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8576 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8577 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8581 /* add sign of "a" */
8582 pic16_addSign(result, MSB32, sign);
8586 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8588 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8589 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8593 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8595 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8596 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8600 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8603 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8604 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8609 /*-----------------------------------------------------------------*/
8610 /* genrshFour - shift four byte by a known amount != 0 */
8611 /*-----------------------------------------------------------------*/
8612 static void genrshFour (operand *result, operand *left,
8613 int shCount, int sign)
8615 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8616 /* if shifting more that 3 bytes */
8617 if(shCount >= 24 ) {
8620 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8622 movLeft2Result(left, MSB32, result, LSB);
8624 pic16_addSign(result, MSB16, sign);
8626 else if(shCount >= 16){
8629 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8631 movLeft2Result(left, MSB24, result, LSB);
8632 movLeft2Result(left, MSB32, result, MSB16);
8634 pic16_addSign(result, MSB24, sign);
8636 else if(shCount >= 8){
8639 shiftRLong(left, MSB16, result, sign);
8640 else if(shCount == 0){
8641 movLeft2Result(left, MSB16, result, LSB);
8642 movLeft2Result(left, MSB24, result, MSB16);
8643 movLeft2Result(left, MSB32, result, MSB24);
8644 pic16_addSign(result, MSB32, sign);
8646 else{ //shcount >= 2
8647 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8648 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8649 /* the last shift is signed */
8650 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8651 pic16_addSign(result, MSB32, sign);
8654 else{ /* 1 <= shCount <= 7 */
8656 shiftRLong(left, LSB, result, sign);
8658 shiftRLong(result, LSB, result, sign);
8661 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8662 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8663 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8668 /*-----------------------------------------------------------------*/
8669 /* genRightShiftLiteral - right shifting by known count */
8670 /*-----------------------------------------------------------------*/
8671 static void genRightShiftLiteral (operand *left,
8677 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8680 pic16_freeAsmop(right,NULL,ic,TRUE);
8682 pic16_aopOp(left,ic,FALSE);
8683 pic16_aopOp(result,ic,FALSE);
8685 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8688 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8692 lsize = pic16_getDataSize(left);
8693 res_size = pic16_getDataSize(result);
8694 /* test the LEFT size !!! */
8696 /* I suppose that the left size >= result size */
8699 movLeft2Result(left, lsize, result, res_size);
8702 else if(shCount >= (lsize * 8)){
8705 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8707 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8708 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8713 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8714 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8715 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8717 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8722 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8729 genrshOne (result,left,shCount,sign);
8733 genrshTwo (result,left,shCount,sign);
8737 genrshFour (result,left,shCount,sign);
8745 pic16_freeAsmop(left,NULL,ic,TRUE);
8746 pic16_freeAsmop(result,NULL,ic,TRUE);
8749 /*-----------------------------------------------------------------*/
8750 /* genSignedRightShift - right shift of signed number */
8751 /*-----------------------------------------------------------------*/
8752 static void genSignedRightShift (iCode *ic)
8754 operand *right, *left, *result;
8757 symbol *tlbl, *tlbl1 ;
8760 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8762 /* we do it the hard way put the shift count in b
8763 and loop thru preserving the sign */
8764 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8766 right = IC_RIGHT(ic);
8768 result = IC_RESULT(ic);
8770 pic16_aopOp(right,ic,FALSE);
8771 pic16_aopOp(left,ic,FALSE);
8772 pic16_aopOp(result,ic,FALSE);
8775 if ( AOP_TYPE(right) == AOP_LIT) {
8776 genRightShiftLiteral (left,right,result,ic,1);
8779 /* shift count is unknown then we have to form
8780 a loop get the loop count in B : Note: we take
8781 only the lower order byte since shifting
8782 more that 32 bits make no sense anyway, ( the
8783 largest size of an object can be only 32 bits ) */
8785 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8786 //pic16_emitcode("inc","b");
8787 //pic16_freeAsmop (right,NULL,ic,TRUE);
8788 //pic16_aopOp(left,ic,FALSE);
8789 //pic16_aopOp(result,ic,FALSE);
8791 /* now move the left to the result if they are not the
8793 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8794 AOP_SIZE(result) > 1) {
8796 size = AOP_SIZE(result);
8800 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8801 if (*l == '@' && IS_AOP_PREG(result)) {
8803 pic16_emitcode("mov","a,%s",l);
8804 pic16_aopPut(AOP(result),"a",offset);
8806 pic16_aopPut(AOP(result),l,offset);
8808 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8809 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8815 /* mov the highest order bit to OVR */
8816 tlbl = newiTempLabel(NULL);
8817 tlbl1= newiTempLabel(NULL);
8819 size = AOP_SIZE(result);
8822 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8824 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8826 /* offset should be 0, 1 or 3 */
8827 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8829 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8831 pic16_emitpcode(POC_MOVWF, pctemp);
8834 pic16_emitpLabel(tlbl->key);
8836 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
8837 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
8840 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
8843 pic16_emitpcode(POC_DECFSZ, pctemp);
8844 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8845 pic16_emitpLabel(tlbl1->key);
8847 pic16_popReleaseTempReg(pctemp);
8849 size = AOP_SIZE(result);
8851 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8852 pic16_emitcode("rlc","a");
8853 pic16_emitcode("mov","ov,c");
8854 /* if it is only one byte then */
8856 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8858 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8859 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8860 pic16_emitcode("mov","c,ov");
8861 pic16_emitcode("rrc","a");
8862 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8863 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8864 pic16_aopPut(AOP(result),"a",0);
8868 reAdjustPreg(AOP(result));
8869 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8870 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8871 pic16_emitcode("mov","c,ov");
8873 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8875 pic16_emitcode("rrc","a");
8876 pic16_aopPut(AOP(result),"a",offset--);
8878 reAdjustPreg(AOP(result));
8879 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8880 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8885 pic16_freeAsmop(left,NULL,ic,TRUE);
8886 pic16_freeAsmop(result,NULL,ic,TRUE);
8887 pic16_freeAsmop(right,NULL,ic,TRUE);
8890 /*-----------------------------------------------------------------*/
8891 /* genRightShift - generate code for right shifting */
8892 /*-----------------------------------------------------------------*/
8893 static void genRightShift (iCode *ic)
8895 operand *right, *left, *result;
8899 symbol *tlbl, *tlbl1 ;
8901 /* if signed then we do it the hard way preserve the
8902 sign bit moving it inwards */
8903 letype = getSpec(operandType(IC_LEFT(ic)));
8904 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8906 if (!SPEC_USIGN(letype)) {
8907 genSignedRightShift (ic);
8911 /* signed & unsigned types are treated the same : i.e. the
8912 signed is NOT propagated inwards : quoting from the
8913 ANSI - standard : "for E1 >> E2, is equivalent to division
8914 by 2**E2 if unsigned or if it has a non-negative value,
8915 otherwise the result is implementation defined ", MY definition
8916 is that the sign does not get propagated */
8918 right = IC_RIGHT(ic);
8920 result = IC_RESULT(ic);
8922 pic16_aopOp(right,ic,FALSE);
8924 /* if the shift count is known then do it
8925 as efficiently as possible */
8926 if (AOP_TYPE(right) == AOP_LIT) {
8927 genRightShiftLiteral (left,right,result,ic, 0);
8931 /* shift count is unknown then we have to form
8932 a loop get the loop count in B : Note: we take
8933 only the lower order byte since shifting
8934 more that 32 bits make no sense anyway, ( the
8935 largest size of an object can be only 32 bits ) */
8937 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8938 pic16_emitcode("inc","b");
8939 pic16_aopOp(left,ic,FALSE);
8940 pic16_aopOp(result,ic,FALSE);
8942 /* now move the left to the result if they are not the
8944 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8945 AOP_SIZE(result) > 1) {
8947 size = AOP_SIZE(result);
8950 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8951 if (*l == '@' && IS_AOP_PREG(result)) {
8953 pic16_emitcode("mov","a,%s",l);
8954 pic16_aopPut(AOP(result),"a",offset);
8956 pic16_aopPut(AOP(result),l,offset);
8961 tlbl = newiTempLabel(NULL);
8962 tlbl1= newiTempLabel(NULL);
8963 size = AOP_SIZE(result);
8966 /* if it is only one byte then */
8969 tlbl = newiTempLabel(NULL);
8970 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8971 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8972 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8975 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8976 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8977 pic16_emitpLabel(tlbl->key);
8978 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8979 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8981 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8986 reAdjustPreg(AOP(result));
8987 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8988 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8991 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8993 pic16_emitcode("rrc","a");
8994 pic16_aopPut(AOP(result),"a",offset--);
8996 reAdjustPreg(AOP(result));
8998 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8999 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9002 pic16_freeAsmop(left,NULL,ic,TRUE);
9003 pic16_freeAsmop (right,NULL,ic,TRUE);
9004 pic16_freeAsmop(result,NULL,ic,TRUE);
9007 /*-----------------------------------------------------------------*/
9008 /* genUnpackBits - generates code for unpacking bits */
9009 /*-----------------------------------------------------------------*/
9010 static void genUnpackBits (operand *result, char *rname, int ptype)
9017 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9018 etype = getSpec(operandType(result));
9020 /* read the first byte */
9027 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9030 pic16_emitcode("clr","a");
9031 pic16_emitcode("movc","a","@a+dptr");
9036 /* if we have bitdisplacement then it fits */
9037 /* into this byte completely or if length is */
9038 /* less than a byte */
9039 if ((shCnt = SPEC_BSTR(etype)) ||
9040 (SPEC_BLEN(etype) <= 8)) {
9042 /* shift right acc */
9045 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9046 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9048 /* VR -- normally I would use the following, but since we use the hack,
9049 * to avoid the masking from AccRsh, why not mask it right now? */
9052 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9055 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9061 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9062 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9065 /* bit field did not fit in a byte */
9066 rlen = SPEC_BLEN(etype) - 8;
9067 pic16_aopPut(AOP(result),"a",offset++);
9074 pic16_emitcode("inc","%s",rname);
9075 pic16_emitcode("mov","a,@%s",rname);
9079 pic16_emitcode("inc","%s",rname);
9080 pic16_emitcode("movx","a,@%s",rname);
9084 pic16_emitcode("inc","dptr");
9085 pic16_emitcode("movx","a,@dptr");
9089 pic16_emitcode("clr","a");
9090 pic16_emitcode("inc","dptr");
9091 pic16_emitcode("movc","a","@a+dptr");
9095 pic16_emitcode("inc","dptr");
9096 pic16_emitcode("lcall","__gptrget");
9101 /* if we are done */
9105 pic16_aopPut(AOP(result),"a",offset++);
9110 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9111 pic16_aopPut(AOP(result),"a",offset);
9118 static void genDataPointerGet(operand *left,
9122 int size, offset = 0, leoffset=0 ;
9124 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9125 pic16_aopOp(result, ic, FALSE);
9127 size = AOP_SIZE(result);
9128 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9132 /* The following tests may save a redudant movff instruction when
9133 * accessing unions */
9135 /* if they are the same */
9136 if (operandsEqu (left, result)) {
9137 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9143 /* if they are the same registers */
9144 if (pic16_sameRegs(AOP(left),AOP(result))) {
9145 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9151 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9152 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9153 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9160 if ( AOP_TYPE(left) == AOP_PCODE) {
9161 fprintf(stderr,"genDataPointerGet %s, %d\n",
9162 AOP(left)->aopu.pcop->name,
9163 (AOP(left)->aopu.pcop->type == PO_DIR)?
9164 PCOR(AOP(left)->aopu.pcop)->instance:
9165 PCOI(AOP(left)->aopu.pcop)->offset);
9169 if(AOP(left)->aopu.pcop->type == PO_DIR)
9170 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9172 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9175 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9177 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9178 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9179 mov2w(AOP(left), offset); // patch 8
9180 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9182 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9183 pic16_popGet(AOP(left), offset), //patch 8
9184 pic16_popGet(AOP(result), offset)));
9192 pic16_freeAsmop(result,NULL,ic,TRUE);
9195 void pic16_loadFSR0(operand *op)
9197 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9201 /*-----------------------------------------------------------------*/
9202 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
9203 /*-----------------------------------------------------------------*/
9204 static void genNearPointerGet (operand *left,
9209 //regs *preg = NULL ;
9210 sym_link *rtype, *retype;
9211 sym_link *ltype = operandType(left);
9213 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9214 rtype = operandType(result);
9215 retype= getSpec(rtype);
9217 pic16_aopOp(left,ic,FALSE);
9219 // pic16_DumpOp("(left)",left);
9220 // pic16_DumpOp("(result)",result);
9222 /* if left is rematerialisable and
9223 * result is not bit variable type and
9224 * the left is pointer to data space i.e
9225 * lower 128 bytes of space */
9226 if (AOP_TYPE(left) == AOP_PCODE
9227 && !IS_BITFIELD(retype)
9228 && DCL_TYPE(ltype) == POINTER) {
9230 genDataPointerGet (left,result,ic);
9231 pic16_freeAsmop(left, NULL, ic, TRUE);
9235 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9237 /* if the value is already in a pointer register
9238 * then don't need anything more */
9239 if (!AOP_INPREG(AOP(left))) {
9240 /* otherwise get a free pointer register */
9241 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9243 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9244 if( (AOP_TYPE(left) == AOP_PCODE)
9245 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9246 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9248 pic16_loadFSR0( left ); // patch 10
9250 // set up FSR0 with address from left
9251 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9252 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9256 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9258 pic16_aopOp (result,ic,FALSE);
9260 /* if bitfield then unpack the bits */
9261 if (IS_BITFIELD(retype))
9262 genUnpackBits (result, NULL, POINTER);
9264 /* we have can just get the values */
9265 int size = AOP_SIZE(result);
9268 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9271 /* fsr0 is loaded already -- VR */
9272 // pic16_loadFSR0( left );
9274 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9275 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9279 pic16_emitpcode(POC_MOVFF,
9280 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9281 pic16_popGet(AOP(result), offset++)));
9283 pic16_emitpcode(POC_MOVFF,
9284 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9285 pic16_popGet(AOP(result), offset++)));
9289 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9290 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9292 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9296 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9298 pic16_emitcode("mov","a,@%s",rname);
9299 pic16_aopPut(AOP(result),"a",offset);
9301 sprintf(buffer,"@%s",rname);
9302 pic16_aopPut(AOP(result),buffer,offset);
9306 pic16_emitcode("inc","%s",rname);
9311 /* now some housekeeping stuff */
9313 /* we had to allocate for this iCode */
9314 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9315 pic16_freeAsmop(NULL,aop,ic,TRUE);
9317 /* we did not allocate which means left
9318 already in a pointer register, then
9319 if size > 0 && this could be used again
9320 we have to point it back to where it
9322 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9323 if (AOP_SIZE(result) > 1 &&
9324 !OP_SYMBOL(left)->remat &&
9325 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9327 // int size = AOP_SIZE(result) - 1;
9329 // pic16_emitcode("dec","%s",rname);
9334 pic16_freeAsmop(left,NULL,ic,TRUE);
9335 pic16_freeAsmop(result,NULL,ic,TRUE);
9339 /*-----------------------------------------------------------------*/
9340 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
9341 /*-----------------------------------------------------------------*/
9342 static void genPagedPointerGet (operand *left,
9349 sym_link *rtype, *retype;
9351 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9353 rtype = operandType(result);
9354 retype= getSpec(rtype);
9356 pic16_aopOp(left,ic,FALSE);
9358 /* if the value is already in a pointer register
9359 then don't need anything more */
9360 if (!AOP_INPREG(AOP(left))) {
9361 /* otherwise get a free pointer register */
9363 preg = getFreePtr(ic,&aop,FALSE);
9364 pic16_emitcode("mov","%s,%s",
9366 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9367 rname = preg->name ;
9369 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9371 pic16_freeAsmop(left,NULL,ic,TRUE);
9372 pic16_aopOp (result,ic,FALSE);
9374 /* if bitfield then unpack the bits */
9375 if (IS_BITFIELD(retype))
9376 genUnpackBits (result,rname,PPOINTER);
9378 /* we have can just get the values */
9379 int size = AOP_SIZE(result);
9384 pic16_emitcode("movx","a,@%s",rname);
9385 pic16_aopPut(AOP(result),"a",offset);
9390 pic16_emitcode("inc","%s",rname);
9394 /* now some housekeeping stuff */
9396 /* we had to allocate for this iCode */
9397 pic16_freeAsmop(NULL,aop,ic,TRUE);
9399 /* we did not allocate which means left
9400 already in a pointer register, then
9401 if size > 0 && this could be used again
9402 we have to point it back to where it
9404 if (AOP_SIZE(result) > 1 &&
9405 !OP_SYMBOL(left)->remat &&
9406 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9408 int size = AOP_SIZE(result) - 1;
9410 pic16_emitcode("dec","%s",rname);
9415 pic16_freeAsmop(result,NULL,ic,TRUE);
9420 /*-----------------------------------------------------------------*/
9421 /* genFarPointerGet - gget value from far space */
9422 /*-----------------------------------------------------------------*/
9423 static void genFarPointerGet (operand *left,
9424 operand *result, iCode *ic)
9427 sym_link *retype = getSpec(operandType(result));
9429 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9431 pic16_aopOp(left,ic,FALSE);
9433 /* if the operand is already in dptr
9434 then we do nothing else we move the value to dptr */
9435 if (AOP_TYPE(left) != AOP_STR) {
9436 /* if this is remateriazable */
9437 if (AOP_TYPE(left) == AOP_IMMD)
9438 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9439 else { /* we need to get it byte by byte */
9440 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9441 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9442 if (options.model == MODEL_FLAT24)
9444 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9448 /* so dptr know contains the address */
9449 pic16_freeAsmop(left,NULL,ic,TRUE);
9450 pic16_aopOp(result,ic,FALSE);
9452 /* if bit then unpack */
9453 if (IS_BITFIELD(retype))
9454 genUnpackBits(result,"dptr",FPOINTER);
9456 size = AOP_SIZE(result);
9460 pic16_emitcode("movx","a,@dptr");
9461 pic16_aopPut(AOP(result),"a",offset++);
9463 pic16_emitcode("inc","dptr");
9467 pic16_freeAsmop(result,NULL,ic,TRUE);
9470 /*-----------------------------------------------------------------*/
9471 /* genCodePointerGet - get value from code space */
9472 /*-----------------------------------------------------------------*/
9473 static void genCodePointerGet (operand *left,
9474 operand *result, iCode *ic)
9477 sym_link *retype = getSpec(operandType(result));
9479 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9481 pic16_aopOp(left,ic,FALSE);
9483 /* if the operand is already in dptr
9484 then we do nothing else we move the value to dptr */
9485 if (AOP_TYPE(left) != AOP_STR) {
9486 /* if this is remateriazable */
9487 if (AOP_TYPE(left) == AOP_IMMD)
9488 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9489 else { /* we need to get it byte by byte */
9490 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9491 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9492 if (options.model == MODEL_FLAT24)
9494 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9498 /* so dptr know contains the address */
9499 pic16_freeAsmop(left,NULL,ic,TRUE);
9500 pic16_aopOp(result,ic,FALSE);
9502 /* if bit then unpack */
9503 if (IS_BITFIELD(retype))
9504 genUnpackBits(result,"dptr",CPOINTER);
9506 size = AOP_SIZE(result);
9510 pic16_emitcode("clr","a");
9511 pic16_emitcode("movc","a,@a+dptr");
9512 pic16_aopPut(AOP(result),"a",offset++);
9514 pic16_emitcode("inc","dptr");
9518 pic16_freeAsmop(result,NULL,ic,TRUE);
9521 /*-----------------------------------------------------------------*/
9522 /* genGenPointerGet - gget value from generic pointer space */
9523 /*-----------------------------------------------------------------*/
9524 static void genGenPointerGet (operand *left,
9525 operand *result, iCode *ic)
9527 int size, offset, lit;
9528 sym_link *retype = getSpec(operandType(result));
9530 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9531 pic16_aopOp(left,ic,FALSE);
9532 pic16_aopOp(result,ic,FALSE);
9533 size = AOP_SIZE(result);
9535 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9537 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9539 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9540 // load FSR0 from immediate
9541 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9543 // pic16_loadFSR0( left );
9548 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9550 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9557 else { /* we need to get it byte by byte */
9558 // set up FSR0 with address from left
9559 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9560 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9566 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9568 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9575 /* if bit then unpack */
9576 if (IS_BITFIELD(retype))
9577 genUnpackBits(result,"BAD",GPOINTER);
9580 pic16_freeAsmop(left,NULL,ic,TRUE);
9581 pic16_freeAsmop(result,NULL,ic,TRUE);
9585 /*-----------------------------------------------------------------*/
9586 /* genConstPointerGet - get value from const generic pointer space */
9587 /*-----------------------------------------------------------------*/
9588 static void genConstPointerGet (operand *left,
9589 operand *result, iCode *ic)
9591 //sym_link *retype = getSpec(operandType(result));
9592 // symbol *albl = newiTempLabel(NULL); // patch 15
9593 // symbol *blbl = newiTempLabel(NULL); //
9594 // PIC_OPCODE poc; // patch 15
9598 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9599 pic16_aopOp(left,ic,FALSE);
9600 pic16_aopOp(result,ic,TRUE);
9601 size = AOP_SIZE(result);
9603 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9605 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9607 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9608 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9609 pic16_emitpLabel(albl->key);
9611 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9613 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9614 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9615 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9616 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9617 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9619 pic16_emitpLabel(blbl->key);
9621 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9625 // set up table pointer
9626 if( (AOP_TYPE(left) == AOP_PCODE)
9627 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9628 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
9630 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9631 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9632 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9633 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9634 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9635 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9639 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9640 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9641 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9647 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9648 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9652 pic16_freeAsmop(left,NULL,ic,TRUE);
9653 pic16_freeAsmop(result,NULL,ic,TRUE);
9658 /*-----------------------------------------------------------------*/
9659 /* genPointerGet - generate code for pointer get */
9660 /*-----------------------------------------------------------------*/
9661 static void genPointerGet (iCode *ic)
9663 operand *left, *result ;
9664 sym_link *type, *etype;
9667 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9670 result = IC_RESULT(ic) ;
9672 /* depending on the type of pointer we need to
9673 move it to the correct pointer register */
9674 type = operandType(left);
9675 etype = getSpec(type);
9678 if (IS_PTR_CONST(type))
9680 if (IS_CODEPTR(type))
9682 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9684 /* if left is of type of pointer then it is simple */
9685 if (IS_PTR(type) && !IS_FUNC(type->next))
9686 p_type = DCL_TYPE(type);
9688 /* we have to go by the storage class */
9689 p_type = PTR_TYPE(SPEC_OCLS(etype));
9691 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9693 if (SPEC_OCLS(etype)->codesp ) {
9694 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9695 //p_type = CPOINTER ;
9698 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9699 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9700 /*p_type = FPOINTER ;*/
9702 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9703 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9704 /* p_type = PPOINTER; */
9706 if (SPEC_OCLS(etype) == idata )
9707 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9708 /* p_type = IPOINTER; */
9710 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9711 /* p_type = POINTER ; */
9714 /* now that we have the pointer type we assign
9715 the pointer values */
9720 genNearPointerGet (left,result,ic);
9724 genPagedPointerGet(left,result,ic);
9728 genFarPointerGet (left,result,ic);
9732 genConstPointerGet (left,result,ic);
9733 //pic16_emitcodePointerGet (left,result,ic);
9738 if (IS_PTR_CONST(type))
9739 genConstPointerGet (left,result,ic);
9742 genGenPointerGet (left,result,ic);
9746 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9747 "genPointerGet: illegal pointer type");
9753 /*-----------------------------------------------------------------*/
9754 /* genPackBits - generates code for packed bit storage */
9755 /*-----------------------------------------------------------------*/
9756 static void genPackBits (sym_link *etype ,
9758 char *rname, int p_type)
9766 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9767 blen = SPEC_BLEN(etype);
9768 bstr = SPEC_BSTR(etype);
9770 if(AOP_TYPE(right) == AOP_LIT) {
9771 if((blen == 1) && (bstr < 8)) {
9773 /* it is a single bit, so use the appropriate bit instructions */
9775 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9777 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9778 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9780 pic16_emitpcode(POC_BSF,
9781 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9783 pic16_emitpcode(POC_BCF,
9784 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9790 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9793 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9795 /* if the bit lenth is less than or */
9796 /* it exactly fits a byte then */
9797 if((shCnt=SPEC_BSTR(etype))
9798 || SPEC_BLEN(etype) <= 8 ) {
9800 /* shift left acc */
9803 /* using PRODL as a temporary register here */
9804 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9810 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9811 // pic16_emitcode ("mov","b,a");
9812 // pic16_emitcode("mov","a,@%s",rname);
9816 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9817 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9818 (unsigned char)(0xff >> (8-bstr))) ));
9819 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9820 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9827 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9828 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9833 if ( SPEC_BLEN(etype) <= 8 )
9836 pic16_emitcode("inc","%s",rname);
9837 rLen = SPEC_BLEN(etype) ;
9841 /* now generate for lengths greater than one byte */
9844 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9854 pic16_emitcode("mov","@%s,a",rname);
9856 pic16_emitcode("mov","@%s,%s",rname,l);
9861 pic16_emitcode("movx","@dptr,a");
9866 DEBUGpic16_emitcode(";lcall","__gptrput");
9869 pic16_emitcode ("inc","%s",rname);
9874 /* last last was not complete */
9876 /* save the byte & read byte */
9879 pic16_emitcode ("mov","b,a");
9880 pic16_emitcode("mov","a,@%s",rname);
9884 pic16_emitcode ("mov","b,a");
9885 pic16_emitcode("movx","a,@dptr");
9889 pic16_emitcode ("push","b");
9890 pic16_emitcode ("push","acc");
9891 pic16_emitcode ("lcall","__gptrget");
9892 pic16_emitcode ("pop","b");
9896 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9897 pic16_emitcode ("orl","a,b");
9900 if (p_type == GPOINTER)
9901 pic16_emitcode("pop","b");
9906 pic16_emitcode("mov","@%s,a",rname);
9910 pic16_emitcode("movx","@dptr,a");
9914 DEBUGpic16_emitcode(";lcall","__gptrput");
9918 /*-----------------------------------------------------------------*/
9919 /* genDataPointerSet - remat pointer to data space */
9920 /*-----------------------------------------------------------------*/
9921 static void genDataPointerSet(operand *right,
9925 int size, offset = 0, resoffset=0 ;
9927 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9928 pic16_aopOp(right,ic,FALSE);
9930 size = AOP_SIZE(right);
9932 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9935 if ( AOP_TYPE(result) == AOP_PCODE) {
9936 fprintf(stderr,"genDataPointerSet %s, %d\n",
9937 AOP(result)->aopu.pcop->name,
9938 (AOP(result)->aopu.pcop->type == PO_DIR)?
9939 PCOR(AOP(result)->aopu.pcop)->instance:
9940 PCOI(AOP(result)->aopu.pcop)->offset);
9944 if(AOP(result)->aopu.pcop->type == PO_DIR)
9945 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9948 if (AOP_TYPE(right) == AOP_LIT) {
9949 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9951 lit = lit >> (8*offset);
9953 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9954 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9956 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9959 mov2w(AOP(right), offset);
9960 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9966 pic16_freeAsmop(right,NULL,ic,TRUE);
9971 /*-----------------------------------------------------------------*/
9972 /* genNearPointerSet - pic16_emitcode for near pointer put */
9973 /*-----------------------------------------------------------------*/
9974 static void genNearPointerSet (operand *right,
9981 sym_link *ptype = operandType(result);
9984 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9985 retype= getSpec(operandType(right));
9986 resetype = getSpec(operandType(result));
9988 pic16_aopOp(result,ic,FALSE);
9990 /* if the result is rematerializable &
9991 * in data space & not a bit variable */
9993 /* and result is not a bit variable */
9994 if (AOP_TYPE(result) == AOP_PCODE
9995 // && AOP_TYPE(result) == AOP_IMMD
9996 && DCL_TYPE(ptype) == POINTER
9997 && !IS_BITFIELD(retype)
9998 && !IS_BITFIELD(resetype)) {
10000 genDataPointerSet (right,result,ic);
10001 pic16_freeAsmop(result,NULL,ic,TRUE);
10005 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10006 pic16_aopOp(right,ic,FALSE);
10007 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10009 /* if the value is already in a pointer register
10010 * then don't need anything more */
10011 if (!AOP_INPREG(AOP(result))) {
10012 /* otherwise get a free pointer register */
10013 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10015 if( (AOP_TYPE(result) == AOP_PCODE)
10016 && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10017 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10019 pic16_loadFSR0( result ); // patch 10
10021 // set up FSR0 with address of result
10022 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10023 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10028 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10030 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10032 /* if bitfield then unpack the bits */
10033 if (IS_BITFIELD(resetype)) {
10034 genPackBits (resetype, right, NULL, POINTER);
10036 /* we have can just get the values */
10037 int size = AOP_SIZE(right);
10040 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10042 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10045 //pic16_emitcode("mov","@%s,a",rname);
10046 pic16_emitcode("movf","indf0,w ;1");
10049 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
10050 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
10052 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
10054 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
10056 } else { // no literal //
10058 pic16_emitpcode(POC_MOVFF, //
10059 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10060 pic16_popCopyReg(&pic16_pc_postinc0))); //
10062 pic16_emitpcode(POC_MOVFF, //
10063 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10064 pic16_popCopyReg(&pic16_pc_indf0))); //
10072 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10073 /* now some housekeeping stuff */
10075 /* we had to allocate for this iCode */
10076 pic16_freeAsmop(NULL,aop,ic,TRUE);
10078 /* we did not allocate which means left
10079 * already in a pointer register, then
10080 * if size > 0 && this could be used again
10081 * we have to point it back to where it
10083 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10084 if (AOP_SIZE(right) > 1
10085 && !OP_SYMBOL(result)->remat
10086 && ( OP_SYMBOL(result)->liveTo > ic->seq
10089 int size = AOP_SIZE(right) - 1;
10092 pic16_emitcode("decf","fsr0,f");
10093 //pic16_emitcode("dec","%s",rname);
10097 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10100 pic16_freeAsmop(right,NULL,ic,TRUE);
10101 pic16_freeAsmop(result,NULL,ic,TRUE);
10104 /*-----------------------------------------------------------------*/
10105 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
10106 /*-----------------------------------------------------------------*/
10107 static void genPagedPointerSet (operand *right,
10112 regs *preg = NULL ;
10116 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10118 retype= getSpec(operandType(right));
10120 pic16_aopOp(result,ic,FALSE);
10122 /* if the value is already in a pointer register
10123 then don't need anything more */
10124 if (!AOP_INPREG(AOP(result))) {
10125 /* otherwise get a free pointer register */
10127 preg = getFreePtr(ic,&aop,FALSE);
10128 pic16_emitcode("mov","%s,%s",
10130 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10131 rname = preg->name ;
10133 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10135 pic16_freeAsmop(result,NULL,ic,TRUE);
10136 pic16_aopOp (right,ic,FALSE);
10138 /* if bitfield then unpack the bits */
10139 if (IS_BITFIELD(retype))
10140 genPackBits (retype,right,rname,PPOINTER);
10142 /* we have can just get the values */
10143 int size = AOP_SIZE(right);
10147 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10150 pic16_emitcode("movx","@%s,a",rname);
10153 pic16_emitcode("inc","%s",rname);
10159 /* now some housekeeping stuff */
10161 /* we had to allocate for this iCode */
10162 pic16_freeAsmop(NULL,aop,ic,TRUE);
10164 /* we did not allocate which means left
10165 already in a pointer register, then
10166 if size > 0 && this could be used again
10167 we have to point it back to where it
10169 if (AOP_SIZE(right) > 1 &&
10170 !OP_SYMBOL(result)->remat &&
10171 ( OP_SYMBOL(result)->liveTo > ic->seq ||
10173 int size = AOP_SIZE(right) - 1;
10175 pic16_emitcode("dec","%s",rname);
10180 pic16_freeAsmop(right,NULL,ic,TRUE);
10185 /*-----------------------------------------------------------------*/
10186 /* genFarPointerSet - set value from far space */
10187 /*-----------------------------------------------------------------*/
10188 static void genFarPointerSet (operand *right,
10189 operand *result, iCode *ic)
10192 sym_link *retype = getSpec(operandType(right));
10194 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10195 pic16_aopOp(result,ic,FALSE);
10197 /* if the operand is already in dptr
10198 then we do nothing else we move the value to dptr */
10199 if (AOP_TYPE(result) != AOP_STR) {
10200 /* if this is remateriazable */
10201 if (AOP_TYPE(result) == AOP_IMMD)
10202 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10203 else { /* we need to get it byte by byte */
10204 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10205 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10206 if (options.model == MODEL_FLAT24)
10208 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10212 /* so dptr know contains the address */
10213 pic16_freeAsmop(result,NULL,ic,TRUE);
10214 pic16_aopOp(right,ic,FALSE);
10216 /* if bit then unpack */
10217 if (IS_BITFIELD(retype))
10218 genPackBits(retype,right,"dptr",FPOINTER);
10220 size = AOP_SIZE(right);
10224 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10226 pic16_emitcode("movx","@dptr,a");
10228 pic16_emitcode("inc","dptr");
10232 pic16_freeAsmop(right,NULL,ic,TRUE);
10235 /*-----------------------------------------------------------------*/
10236 /* genGenPointerSet - set value from generic pointer space */
10237 /*-----------------------------------------------------------------*/
10238 static void genGenPointerSet (operand *right,
10239 operand *result, iCode *ic)
10241 int i, size, offset, lit;
10242 sym_link *retype = getSpec(operandType(right));
10244 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10246 pic16_aopOp(result,ic,FALSE);
10247 pic16_aopOp(right,ic,FALSE);
10248 size = AOP_SIZE(right);
10251 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10253 /* if the operand is already in dptr
10254 then we do nothing else we move the value to dptr */
10255 if (AOP_TYPE(result) != AOP_STR) {
10256 /* if this is remateriazable */
10257 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10258 // WARNING: anythig until "else" is untested!
10259 if (AOP_TYPE(result) == AOP_IMMD) {
10260 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10261 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10262 // load FSR0 from immediate
10263 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10267 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10269 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10275 else { /* we need to get it byte by byte */
10276 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10277 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10279 // set up FSR0 with address of result
10280 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10281 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10283 /* hack hack! see if this the FSR. If so don't load W */
10284 if(AOP_TYPE(right) != AOP_ACC) {
10286 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10288 if(AOP_TYPE(right) == AOP_LIT)
10291 // note: pic16_popGet handles sign extension
10292 for(i=0;i<size;i++) {
10293 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10295 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10297 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10302 for(i=0;i<size;i++) {
10304 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10305 pic16_popCopyReg(&pic16_pc_postinc0)));
10307 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10308 pic16_popCopyReg(&pic16_pc_indf0)));
10314 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10315 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10317 } // if (AOP_TYPE(result) != AOP_IMMD)
10319 } // if (AOP_TYPE(result) != AOP_STR)
10320 /* so dptr know contains the address */
10323 /* if bit then unpack */
10324 if (IS_BITFIELD(retype))
10325 genPackBits(retype,right,"dptr",GPOINTER);
10327 size = AOP_SIZE(right);
10330 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
10332 // set up FSR0 with address of result
10333 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10334 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10337 if (AOP_TYPE(right) == AOP_LIT) {
10338 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10340 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10342 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10344 } else { // no literal
10346 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10348 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10356 pic16_freeAsmop(right,NULL,ic,TRUE);
10357 pic16_freeAsmop(result,NULL,ic,TRUE);
10360 /*-----------------------------------------------------------------*/
10361 /* genPointerSet - stores the value into a pointer location */
10362 /*-----------------------------------------------------------------*/
10363 static void genPointerSet (iCode *ic)
10365 operand *right, *result ;
10366 sym_link *type, *etype;
10369 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10371 right = IC_RIGHT(ic);
10372 result = IC_RESULT(ic) ;
10374 /* depending on the type of pointer we need to
10375 move it to the correct pointer register */
10376 type = operandType(result);
10377 etype = getSpec(type);
10378 /* if left is of type of pointer then it is simple */
10379 if (IS_PTR(type) && !IS_FUNC(type->next)) {
10380 p_type = DCL_TYPE(type);
10383 /* we have to go by the storage class */
10384 p_type = PTR_TYPE(SPEC_OCLS(etype));
10386 /* if (SPEC_OCLS(etype)->codesp ) { */
10387 /* p_type = CPOINTER ; */
10390 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10391 /* p_type = FPOINTER ; */
10393 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10394 /* p_type = PPOINTER ; */
10396 /* if (SPEC_OCLS(etype) == idata ) */
10397 /* p_type = IPOINTER ; */
10399 /* p_type = POINTER ; */
10402 /* now that we have the pointer type we assign
10403 the pointer values */
10408 genNearPointerSet (right,result,ic);
10412 genPagedPointerSet (right,result,ic);
10416 genFarPointerSet (right,result,ic);
10420 genGenPointerSet (right,result,ic);
10424 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10425 "genPointerSet: illegal pointer type");
10429 /*-----------------------------------------------------------------*/
10430 /* genIfx - generate code for Ifx statement */
10431 /*-----------------------------------------------------------------*/
10432 static void genIfx (iCode *ic, iCode *popIc)
10434 operand *cond = IC_COND(ic);
10437 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10439 pic16_aopOp(cond,ic,FALSE);
10441 /* get the value into acc */
10442 if (AOP_TYPE(cond) != AOP_CRY)
10443 pic16_toBoolean(cond);
10446 /* the result is now in the accumulator */
10447 pic16_freeAsmop(cond,NULL,ic,TRUE);
10449 /* if there was something to be popped then do it */
10453 /* if the condition is a bit variable */
10454 if (isbit && IS_ITEMP(cond) &&
10456 genIfxJump(ic,SPIL_LOC(cond)->rname);
10457 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10460 if (isbit && !IS_ITEMP(cond))
10461 genIfxJump(ic,OP_SYMBOL(cond)->rname);
10463 genIfxJump(ic,"a");
10469 /*-----------------------------------------------------------------*/
10470 /* genAddrOf - generates code for address of */
10471 /*-----------------------------------------------------------------*/
10472 static void genAddrOf (iCode *ic)
10474 operand *result, *left;
10476 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
10477 pCodeOp *pcop0, *pcop1, *pcop2;
10479 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10481 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10482 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10484 sym = OP_SYMBOL( left );
10486 size = AOP_SIZE(IC_RESULT(ic));
10488 // if(pic16_debug_verbose) {
10489 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10490 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10493 /* Assume that what we want the address of is in data space
10494 * since there is no stack on the PIC, yet! -- VR */
10496 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10499 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10502 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10506 pic16_emitpcode(POC_MOVLW, pcop0);
10507 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10508 pic16_emitpcode(POC_MOVLW, pcop1);
10509 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10510 pic16_emitpcode(POC_MOVLW, pcop2);
10511 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10514 pic16_emitpcode(POC_MOVLW, pcop0);
10515 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10516 pic16_emitpcode(POC_MOVLW, pcop1);
10517 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10519 pic16_emitpcode(POC_MOVLW, pcop0);
10520 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10523 pic16_freeAsmop(result,NULL,ic,TRUE);
10524 pic16_freeAsmop(left, NULL, ic, FALSE);
10529 /*-----------------------------------------------------------------*/
10530 /* genFarFarAssign - assignment when both are in far space */
10531 /*-----------------------------------------------------------------*/
10532 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10534 int size = AOP_SIZE(right);
10537 /* first push the right side on to the stack */
10539 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10541 pic16_emitcode ("push","acc");
10544 pic16_freeAsmop(right,NULL,ic,FALSE);
10545 /* now assign DPTR to result */
10546 pic16_aopOp(result,ic,FALSE);
10547 size = AOP_SIZE(result);
10549 pic16_emitcode ("pop","acc");
10550 pic16_aopPut(AOP(result),"a",--offset);
10552 pic16_freeAsmop(result,NULL,ic,FALSE);
10557 /*-----------------------------------------------------------------*/
10558 /* genAssign - generate code for assignment */
10559 /*-----------------------------------------------------------------*/
10560 static void genAssign (iCode *ic)
10562 operand *result, *right;
10563 int size, offset,know_W;
10564 unsigned long lit = 0L;
10566 result = IC_RESULT(ic);
10567 right = IC_RIGHT(ic) ;
10569 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10571 /* if they are the same */
10572 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10575 pic16_aopOp(right,ic,FALSE);
10576 pic16_aopOp(result,ic,TRUE);
10578 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10580 /* if they are the same registers */
10581 if (pic16_sameRegs(AOP(right),AOP(result)))
10584 /* if the result is a bit */
10585 if (AOP_TYPE(result) == AOP_CRY) {
10586 /* if the right size is a literal then
10587 we know what the value is */
10588 if (AOP_TYPE(right) == AOP_LIT) {
10590 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10591 pic16_popGet(AOP(result),0));
10593 if (((int) operandLitValue(right)))
10594 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10595 AOP(result)->aopu.aop_dir,
10596 AOP(result)->aopu.aop_dir);
10598 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10599 AOP(result)->aopu.aop_dir,
10600 AOP(result)->aopu.aop_dir);
10604 /* the right is also a bit variable */
10605 if (AOP_TYPE(right) == AOP_CRY) {
10606 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10607 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10608 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10610 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10611 AOP(result)->aopu.aop_dir,
10612 AOP(result)->aopu.aop_dir);
10613 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10614 AOP(right)->aopu.aop_dir,
10615 AOP(right)->aopu.aop_dir);
10616 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10617 AOP(result)->aopu.aop_dir,
10618 AOP(result)->aopu.aop_dir);
10622 /* we need to or */
10623 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10624 pic16_toBoolean(right);
10626 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10627 //pic16_aopPut(AOP(result),"a",0);
10631 /* bit variables done */
10633 size = AOP_SIZE(result);
10636 if(AOP_TYPE(right) == AOP_LIT) {
10637 if(!IS_FLOAT(operandType( right )))
10638 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10641 unsigned long lit_int;
10645 /* take care if literal is a float */
10646 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10647 lit = info.lit_int;
10651 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10652 // sizeof(unsigned long int), sizeof(float));
10654 if(AOP_TYPE(right) != AOP_LIT
10655 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10656 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10658 // set up table pointer
10659 if( (AOP_TYPE(right) == AOP_PCODE)
10660 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10661 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10663 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10664 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10665 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10666 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10667 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10668 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10670 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10671 pic16_popCopyReg(&pic16_pc_tblptrl)));
10672 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10673 pic16_popCopyReg(&pic16_pc_tblptrh)));
10674 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10675 pic16_popCopyReg(&pic16_pc_tblptru)));
10678 size = min(AOP_SIZE(right), AOP_SIZE(result));
10680 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10681 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10682 pic16_popGet(AOP(result),offset)));
10686 if(AOP_SIZE(result) > AOP_SIZE(right)) {
10687 size = AOP_SIZE(result) - AOP_SIZE(right);
10689 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10698 /* VR - What is this?! */
10699 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10700 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10701 if(aopIdx(AOP(result),0) == 4) {
10702 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10704 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10705 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10709 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10714 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10715 if(AOP_TYPE(right) == AOP_LIT) {
10717 if(know_W != (lit&0xff))
10718 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10720 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10722 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10726 } else if (AOP_TYPE(right) == AOP_CRY) {
10727 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10729 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10730 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10732 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10733 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10734 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10736 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10739 /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10740 normally should work, but mind that the W register live range
10741 is not checked, so if the code generator assumes that the W
10742 is already loaded after such a pair, wrong code will be generated.
10744 Checking the live range is the next step.
10745 This is experimental code yet and has not been fully tested yet.
10746 USE WITH CARE. Revert to old code by setting 0 to the condition above.
10747 Vangelis Rokas 030603 (vrokas@otenet.gr) */
10749 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10751 /* This is the old code, which is assumed(?!) that works fine(!?) */
10753 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10754 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10763 pic16_freeAsmop (right,NULL,ic,FALSE);
10764 pic16_freeAsmop (result,NULL,ic,TRUE);
10767 /*-----------------------------------------------------------------*/
10768 /* genJumpTab - generates code for jump table */
10769 /*-----------------------------------------------------------------*/
10770 static void genJumpTab (iCode *ic)
10775 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10777 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10778 /* get the condition into accumulator */
10779 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10781 /* multiply by three */
10782 pic16_emitcode("add","a,acc");
10783 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10785 jtab = newiTempLabel(NULL);
10786 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10787 pic16_emitcode("jmp","@a+dptr");
10788 pic16_emitcode("","%05d_DS_:",jtab->key+100);
10790 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10791 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10793 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10794 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10795 pic16_emitpLabel(jtab->key);
10797 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10799 /* now generate the jump labels */
10800 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10801 jtab = setNextItem(IC_JTLABELS(ic))) {
10802 pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10803 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10809 /*-----------------------------------------------------------------*/
10810 /* genMixedOperation - gen code for operators between mixed types */
10811 /*-----------------------------------------------------------------*/
10813 TSD - Written for the PIC port - but this unfortunately is buggy.
10814 This routine is good in that it is able to efficiently promote
10815 types to different (larger) sizes. Unfortunately, the temporary
10816 variables that are optimized out by this routine are sometimes
10817 used in other places. So until I know how to really parse the
10818 iCode tree, I'm going to not be using this routine :(.
10820 static int genMixedOperation (iCode *ic)
10823 operand *result = IC_RESULT(ic);
10824 sym_link *ctype = operandType(IC_LEFT(ic));
10825 operand *right = IC_RIGHT(ic);
10831 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10833 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10839 nextright = IC_RIGHT(nextic);
10840 nextleft = IC_LEFT(nextic);
10841 nextresult = IC_RESULT(nextic);
10843 pic16_aopOp(right,ic,FALSE);
10844 pic16_aopOp(result,ic,FALSE);
10845 pic16_aopOp(nextright, nextic, FALSE);
10846 pic16_aopOp(nextleft, nextic, FALSE);
10847 pic16_aopOp(nextresult, nextic, FALSE);
10849 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10851 operand *t = right;
10855 pic16_emitcode(";remove right +","");
10857 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10859 operand *t = right;
10863 pic16_emitcode(";remove left +","");
10867 big = AOP_SIZE(nextleft);
10868 small = AOP_SIZE(nextright);
10870 switch(nextic->op) {
10873 pic16_emitcode(";optimize a +","");
10874 /* if unsigned or not an integral type */
10875 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10876 pic16_emitcode(";add a bit to something","");
10879 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10881 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10882 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10883 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10885 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10893 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10894 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10895 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10898 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10900 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10901 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10902 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10903 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10904 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10907 pic16_emitcode("rlf","known_zero,w");
10914 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10915 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10916 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10918 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10928 pic16_freeAsmop(right,NULL,ic,TRUE);
10929 pic16_freeAsmop(result,NULL,ic,TRUE);
10930 pic16_freeAsmop(nextright,NULL,ic,TRUE);
10931 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10933 nextic->generated = 1;
10940 /*-----------------------------------------------------------------*/
10941 /* genCast - gen code for casting */
10942 /*-----------------------------------------------------------------*/
10943 static void genCast (iCode *ic)
10945 operand *result = IC_RESULT(ic);
10946 sym_link *ctype = operandType(IC_LEFT(ic));
10947 sym_link *rtype = operandType(IC_RIGHT(ic));
10948 operand *right = IC_RIGHT(ic);
10951 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10952 /* if they are equivalent then do nothing */
10953 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10956 pic16_aopOp(right,ic,FALSE) ;
10957 pic16_aopOp(result,ic,FALSE);
10959 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10961 /* if the result is a bit */
10962 if (AOP_TYPE(result) == AOP_CRY) {
10964 /* if the right size is a literal then
10965 * we know what the value is */
10966 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
10968 if (AOP_TYPE(right) == AOP_LIT) {
10969 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10970 pic16_popGet(AOP(result),0));
10972 if (((int) operandLitValue(right)))
10973 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10974 AOP(result)->aopu.aop_dir,
10975 AOP(result)->aopu.aop_dir);
10977 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10978 AOP(result)->aopu.aop_dir,
10979 AOP(result)->aopu.aop_dir);
10983 /* the right is also a bit variable */
10984 if (AOP_TYPE(right) == AOP_CRY) {
10986 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10988 pic16_emitcode("clrc","");
10989 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10990 AOP(right)->aopu.aop_dir,
10991 AOP(right)->aopu.aop_dir);
10992 pic16_aopPut(AOP(result),"c",0);
10996 /* we need to or */
10997 if (AOP_TYPE(right) == AOP_REG) {
10998 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10999 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
11000 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
11002 pic16_toBoolean(right);
11003 pic16_aopPut(AOP(result),"a",0);
11007 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11010 size = AOP_SIZE(result);
11012 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11014 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
11015 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11016 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
11019 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11024 /* if they are the same size : or less */
11025 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11027 /* if they are in the same place */
11028 if (pic16_sameRegs(AOP(right),AOP(result)))
11031 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11033 if (IS_PTR_CONST(rtype))
11035 if (IS_CODEPTR(rtype))
11037 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11040 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11042 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11044 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11047 if(AOP_TYPE(right) == AOP_IMMD) {
11048 pCodeOp *pcop0, *pcop1, *pcop2;
11049 symbol *sym = OP_SYMBOL( right );
11051 size = AOP_SIZE(result);
11053 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11055 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11057 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11060 pic16_emitpcode(POC_MOVLW, pcop0);
11061 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11062 pic16_emitpcode(POC_MOVLW, pcop1);
11063 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11064 pic16_emitpcode(POC_MOVLW, pcop2);
11065 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11068 pic16_emitpcode(POC_MOVLW, pcop0);
11069 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11070 pic16_emitpcode(POC_MOVLW, pcop1);
11071 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11073 pic16_emitpcode(POC_MOVLW, pcop0);
11074 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11078 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11079 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11080 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11081 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11082 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11083 if(AOP_SIZE(result) <2)
11084 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11086 /* if they in different places then copy */
11087 size = AOP_SIZE(result);
11090 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11091 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11098 /* if the result is of type pointer */
11099 if (IS_PTR(ctype)) {
11101 sym_link *type = operandType(right);
11102 sym_link *etype = getSpec(type);
11104 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
11106 /* pointer to generic pointer */
11107 if (IS_GENPTR(ctype)) {
11111 p_type = DCL_TYPE(type);
11113 /* we have to go by the storage class */
11114 p_type = PTR_TYPE(SPEC_OCLS(etype));
11116 /* if (SPEC_OCLS(etype)->codesp ) */
11117 /* p_type = CPOINTER ; */
11119 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11120 /* p_type = FPOINTER ; */
11122 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11123 /* p_type = PPOINTER; */
11125 /* if (SPEC_OCLS(etype) == idata ) */
11126 /* p_type = IPOINTER ; */
11128 /* p_type = POINTER ; */
11131 /* the first two bytes are known */
11132 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
11133 size = GPTRSIZE - 1;
11136 if(offset < AOP_SIZE(right)) {
11137 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
11138 if ((AOP_TYPE(right) == AOP_PCODE) &&
11139 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11140 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11141 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11143 pic16_aopPut(AOP(result),
11144 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11148 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11151 /* the last byte depending on type */
11155 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11158 pic16_emitcode(";BUG!? ","%d",__LINE__);
11162 pic16_emitcode(";BUG!? ","%d",__LINE__);
11166 pic16_emitcode(";BUG!? ","%d",__LINE__);
11171 /* this should never happen */
11172 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11173 "got unknown pointer type");
11176 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
11180 /* just copy the pointers */
11181 size = AOP_SIZE(result);
11184 pic16_aopPut(AOP(result),
11185 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11194 /* so we now know that the size of destination is greater
11195 than the size of the source.
11196 Now, if the next iCode is an operator then we might be
11197 able to optimize the operation without performing a cast.
11199 if(genMixedOperation(ic))
11202 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11204 /* we move to result for the size of source */
11205 size = AOP_SIZE(right);
11208 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11209 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11213 /* now depending on the sign of the destination */
11214 size = AOP_SIZE(result) - AOP_SIZE(right);
11215 /* if unsigned or not an integral type */
11216 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11218 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11220 /* we need to extend the sign :( */
11223 /* Save one instruction of casting char to int */
11224 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11225 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11226 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
11228 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11231 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11233 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11235 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
11238 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
11243 pic16_freeAsmop(right,NULL,ic,TRUE);
11244 pic16_freeAsmop(result,NULL,ic,TRUE);
11248 /*-----------------------------------------------------------------*/
11249 /* genDjnz - generate decrement & jump if not zero instrucion */
11250 /*-----------------------------------------------------------------*/
11251 static int genDjnz (iCode *ic, iCode *ifx)
11253 symbol *lbl, *lbl1;
11254 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11259 /* if the if condition has a false label
11260 then we cannot save */
11264 /* if the minus is not of the form
11266 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11267 !IS_OP_LITERAL(IC_RIGHT(ic)))
11270 if (operandLitValue(IC_RIGHT(ic)) != 1)
11273 /* if the size of this greater than one then no
11275 if (getSize(operandType(IC_RESULT(ic))) > 1)
11278 /* otherwise we can save BIG */
11279 lbl = newiTempLabel(NULL);
11280 lbl1= newiTempLabel(NULL);
11282 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11284 if (IS_AOP_PREG(IC_RESULT(ic))) {
11285 pic16_emitcode("dec","%s",
11286 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11287 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11288 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11292 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11293 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11295 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11296 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
11299 /* pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11300 /* pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11301 /* pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11302 /* pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11305 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11306 ifx->generated = 1;
11310 /*-----------------------------------------------------------------*/
11311 /* genReceive - generate code for a receive iCode */
11312 /*-----------------------------------------------------------------*/
11313 static void genReceive (iCode *ic)
11315 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11318 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11319 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
11321 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11323 if (isOperandInFarSpace(IC_RESULT(ic)) &&
11324 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11325 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11327 int size = getSize(operandType(IC_RESULT(ic)));
11328 int offset = pic16_fReturnSizePic - size;
11332 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11333 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11337 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
11339 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11340 size = AOP_SIZE(IC_RESULT(ic));
11343 pic16_emitcode ("pop","acc");
11344 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11347 DEBUGpic16_emitcode ("; ***","2 %s %d",__FUNCTION__,__LINE__);
11350 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11352 assignResultValue(IC_RESULT(ic), 0);
11355 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11358 /*-----------------------------------------------------------------*/
11359 /* genDummyRead - generate code for dummy read of volatiles */
11360 /*-----------------------------------------------------------------*/
11362 genDummyRead (iCode * ic)
11364 pic16_emitcode ("; genDummyRead","");
11365 pic16_emitcode ("; not implemented","");
11370 /*-----------------------------------------------------------------*/
11371 /* genpic16Code - generate code for pic16 based controllers */
11372 /*-----------------------------------------------------------------*/
11374 * At this point, ralloc.c has gone through the iCode and attempted
11375 * to optimize in a way suitable for a PIC. Now we've got to generate
11376 * PIC instructions that correspond to the iCode.
11378 * Once the instructions are generated, we'll pass through both the
11379 * peep hole optimizer and the pCode optimizer.
11380 *-----------------------------------------------------------------*/
11382 void genpic16Code (iCode *lic)
11387 lineHead = lineCurr = NULL;
11389 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11390 pic16_addpBlock(pb);
11393 /* if debug information required */
11394 if (options.debug && currFunc) {
11396 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11401 for (ic = lic ; ic ; ic = ic->next ) {
11403 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11404 if ( cln != ic->lineno ) {
11405 if ( options.debug ) {
11406 debugFile->writeCLine (ic);
11409 if(!options.noCcodeInAsm) {
11410 pic16_addpCode2pBlock(pb,
11411 pic16_newpCodeCSource(ic->lineno, ic->filename,
11412 printCLine(ic->filename, ic->lineno)));
11418 if(options.iCodeInAsm) {
11420 /* insert here code to print iCode as comment */
11421 l = Safe_strdup(printILine(ic));
11422 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11425 /* if the result is marked as
11426 spilt and rematerializable or code for
11427 this has already been generated then
11429 if (resultRemat(ic) || ic->generated )
11432 /* depending on the operation */
11451 /* IPOP happens only when trying to restore a
11452 spilt live range, if there is an ifx statement
11453 following this pop then the if statement might
11454 be using some of the registers being popped which
11455 would destroy the contents of the register so
11456 we need to check for this condition and handle it */
11458 ic->next->op == IFX &&
11459 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
11460 genIfx (ic->next,ic);
11478 genEndFunction (ic);
11494 pic16_genPlus (ic) ;
11498 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11499 pic16_genMinus (ic);
11515 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
11519 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11526 /* note these two are xlated by algebraic equivalence
11527 during parsing SDCC.y */
11528 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11529 "got '>=' or '<=' shouldn't have come here");
11533 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11545 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11549 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11553 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11577 genRightShift (ic);
11580 case GET_VALUE_AT_ADDRESS:
11585 if (POINTER_SET(ic))
11612 addSet(&_G.sendSet,ic);
11615 case DUMMY_READ_VOLATILE:
11625 /* now we are ready to call the
11626 peep hole optimizer */
11627 if (!options.nopeep) {
11628 peepHole (&lineHead);
11630 /* now do the actual printing */
11631 printLine (lineHead,codeOutFile);
11634 DFPRINTF((stderr,"printing pBlock\n\n"));
11635 pic16_printpBlock(stdout,pb);