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,2004)
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 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst);
81 unsigned int pic16aopLiteral (value *val, int offset);
82 const char *pic16_AopType(short type);
83 static iCode *ifxForOp ( operand *op, iCode *ic );
85 void pic16_pushpCodeOp(pCodeOp *pcop);
86 void pic16_poppCodeOp(pCodeOp *pcop);
88 static bool is_LitOp(operand *op);
89 static bool is_LitAOp(asmop *aop);
92 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
94 /* this is the down and dirty file with all kinds of
95 kludgy & hacky stuff. This is what it is all about
96 CODE GENERATION for a specific MCU . some of the
97 routines may be reusable, will have to see */
99 static char *zero = "#0x00";
100 static char *one = "#0x01";
101 static char *spname = "sp";
105 * Function return value policy (MSB-->LSB):
107 * 16 bits -> PRODL:WREG
108 * 24 bits -> PRODH:PRODL:WREG
109 * 32 bits -> FSR0L:PRODH:PRODL:WREG
110 * >32 bits -> on stack, and FSR0 points to the beginning
115 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
116 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
117 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
118 static char **fReturn = fReturnpic16;
120 static char *accUse[] = {"WREG"};
122 //static short rbank = -1;
138 /* Resolved ifx structure. This structure stores information
139 about an iCode ifx that makes it easier to generate code.
141 typedef struct resolvedIfx {
142 symbol *lbl; /* pointer to a label */
143 int condition; /* true or false ifx */
144 int generated; /* set true when the code associated with the ifx
148 extern int pic16_ptrRegReq ;
149 extern int pic16_nRegs;
150 extern FILE *codeOutFile;
151 static void saverbank (int, iCode *,bool);
153 static lineNode *lineHead = NULL;
154 static lineNode *lineCurr = NULL;
156 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
157 0xE0, 0xC0, 0x80, 0x00};
158 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
159 0x07, 0x03, 0x01, 0x00};
163 /*-----------------------------------------------------------------*/
164 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
165 /* exponent of 2 is returned, otherwise -1 is */
167 /* note that this is similar to the function `powof2' in SDCCsymt */
171 /*-----------------------------------------------------------------*/
172 static int my_powof2 (unsigned long num)
175 if( (num & (num-1)) == 0) {
188 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
190 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
192 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
193 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
194 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
195 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
196 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
197 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
198 ((result) ? AOP_SIZE(result) : 0));
201 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
204 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
206 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
207 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
208 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
209 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
210 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
211 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
215 void pic16_emitpcomment (char *fmt, ...)
218 char lb[INITIAL_INLINEASM];
224 vsprintf(lb+1,fmt,ap);
226 while (isspace(*lbp)) lbp++;
229 lineCurr = (lineCurr ?
230 connectLine(lineCurr,newLineNode(lb)) :
231 (lineHead = newLineNode(lb)));
232 lineCurr->isInline = _G.inLine;
233 lineCurr->isDebug = _G.debugLine;
235 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
238 // fprintf(stderr, "%s\n", lb);
241 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
244 char lb[INITIAL_INLINEASM];
247 if(!pic16_debug_verbose)
254 sprintf(lb,"%s\t",inst);
256 sprintf(lb,"%s",inst);
257 vsprintf(lb+(strlen(lb)),fmt,ap);
261 while (isspace(*lbp)) lbp++;
264 lineCurr = (lineCurr ?
265 connectLine(lineCurr,newLineNode(lb)) :
266 (lineHead = newLineNode(lb)));
267 lineCurr->isInline = _G.inLine;
268 lineCurr->isDebug = _G.debugLine;
270 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
273 // fprintf(stderr, "%s\n", lb);
276 void pic16_emitpLabel(int key)
278 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
281 void pic16_emitpLabelFORCE(int key)
283 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
286 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
290 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
292 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
294 // fprintf(stderr, "%s\n", pcop->name);
297 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
300 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
306 #define pic16_emitcode DEBUGpic16_emitcode
308 /*-----------------------------------------------------------------*/
309 /* pic16_emitcode - writes the code into a file : for now it is simple */
310 /*-----------------------------------------------------------------*/
311 void pic16_emitcode (char *inst,char *fmt, ...)
314 char lb[INITIAL_INLINEASM];
321 sprintf(lb,"%s\t",inst);
323 sprintf(lb,"%s",inst);
324 vsprintf(lb+(strlen(lb)),fmt,ap);
328 while (isspace(*lbp)) lbp++;
331 lineCurr = (lineCurr ?
332 connectLine(lineCurr,newLineNode(lb)) :
333 (lineHead = newLineNode(lb)));
334 lineCurr->isInline = _G.inLine;
335 lineCurr->isDebug = _G.debugLine;
337 // VR fprintf(stderr, "lb = <%s>\n", lbp);
339 // if(pic16_debug_verbose)
340 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
347 /*-----------------------------------------------------------------*/
348 /* pic16_emitDebuggerSymbol - associate the current code location */
349 /* with a debugger symbol */
350 /*-----------------------------------------------------------------*/
352 pic16_emitDebuggerSymbol (char * debugSym)
355 pic16_emitcode (";", "%s ==.", debugSym);
360 /*-----------------------------------------------------------------*/
361 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
362 /*-----------------------------------------------------------------*/
363 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
365 // bool r0iu = FALSE , r1iu = FALSE;
366 // bool r0ou = FALSE , r1ou = FALSE;
367 bool fsr0iu = FALSE, fsr0ou;
368 bool fsr2iu = FALSE, fsr2ou;
370 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
373 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
374 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
376 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
377 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
379 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
380 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
381 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
384 /* no usage of FSR2 */
385 if(!fsr2iu && !fsr2ou) {
386 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
387 (*aopp)->type = AOP_FSR2;
389 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
392 if(!fsr0iu && !fsr0ou) {
393 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
394 (*aopp)->type = AOP_FSR0;
396 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
399 /* now we know they both have usage */
400 /* if fsr0 not used in this instruction */
402 if (!_G.fsr0Pushed) {
403 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
404 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
408 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
409 (*aopp)->type = AOP_FSR0;
411 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
415 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
420 /* the logic: if r0 & r1 used in the instruction
421 then we are in trouble otherwise */
423 /* first check if r0 & r1 are used by this
424 instruction, in which case we are in trouble */
425 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
426 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
431 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
432 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
434 /* if no usage of r0 then return it */
435 if (!r0iu && !r0ou) {
436 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
437 (*aopp)->type = AOP_R0;
439 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
442 /* if no usage of r1 then return it */
443 if (!r1iu && !r1ou) {
444 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
445 (*aopp)->type = AOP_R1;
447 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
450 /* now we know they both have usage */
451 /* if r0 not used in this instruction */
453 /* push it if not already pushed */
455 //pic16_emitcode ("push","%s",
456 // pic16_regWithIdx(R0_IDX)->dname);
460 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
461 (*aopp)->type = AOP_R0;
463 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
466 /* if r1 not used then */
469 /* push it if not already pushed */
471 //pic16_emitcode ("push","%s",
472 // pic16_regWithIdx(R1_IDX)->dname);
476 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
477 (*aopp)->type = AOP_R1;
478 return pic16_regWithIdx(R1_IDX);
482 /* I said end of world but not quite end of world yet */
483 /* if this is a result then we can push it on the stack*/
485 (*aopp)->type = AOP_STK;
489 /* other wise this is true end of the world */
490 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
491 "getFreePtr should never reach here");
496 /*-----------------------------------------------------------------*/
497 /* newAsmop - creates a new asmOp */
498 /*-----------------------------------------------------------------*/
499 static asmop *newAsmop (short type)
503 aop = Safe_calloc(1,sizeof(asmop));
508 static void genSetDPTR(int n)
512 pic16_emitcode(";", "Select standard DPTR");
513 pic16_emitcode("mov", "dps, #0x00");
517 pic16_emitcode(";", "Select alternate DPTR");
518 pic16_emitcode("mov", "dps, #0x01");
522 /*-----------------------------------------------------------------*/
523 /* resolveIfx - converts an iCode ifx into a form more useful for */
524 /* generating code */
525 /*-----------------------------------------------------------------*/
526 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
529 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
535 resIfx->condition = 1; /* assume that the ifx is true */
536 resIfx->generated = 0; /* indicate that the ifx has not been used */
539 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
542 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
543 __FUNCTION__,__LINE__,resIfx->lbl->key);
548 resIfx->lbl = IC_TRUE(ifx);
550 resIfx->lbl = IC_FALSE(ifx);
551 resIfx->condition = 0;
556 DEBUGpic16_emitcode("; ***","ifx true is non-null");
558 DEBUGpic16_emitcode("; ***","ifx false is non-null");
562 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
566 /*-----------------------------------------------------------------*/
567 /* pointerCode - returns the code for a pointer type */
568 /*-----------------------------------------------------------------*/
569 static int pointerCode (sym_link *etype)
572 return PTR_TYPE(SPEC_OCLS(etype));
577 /*-----------------------------------------------------------------*/
578 /* aopForSym - for a true symbol */
579 /*-----------------------------------------------------------------*/
580 static asmop *aopForSym (iCode *ic, operand *op, bool result)
582 symbol *sym=OP_SYMBOL(op);
584 memmap *space= SPEC_OCLS(sym->etype);
586 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
588 // sym = OP_SYMBOL(op);
590 /* if already has one */
592 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
596 /* if symbol was initially placed onStack then we must re-place it
597 * to direct memory, since pic16 does not have a specific stack */
599 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
604 /* assign depending on the storage class */
605 /* if it is on the stack or indirectly addressable */
606 /* space we need to assign either r0 or r1 to it */
607 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
609 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
610 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
612 sym->aop = aop = newAsmop(0);
613 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
614 aop->size = getSize(sym->type);
616 fprintf(stderr, "%s:%d\t%s\n", __FILE__, __LINE__, __FUNCTION__);
619 // sym->aop = aop = newAsmop (AOP_REG);
620 // aop->aopu.aop_dir = sym->name; //sym->rname ;
621 // aop->aopu.aop_reg[0] = pic16_regWithIdx(IDX_PLUSW0); //pic16_pc_plusw2.r;
622 // aop->size = getSize(sym->type);
623 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
626 // pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
629 // pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_fsr2l), pic16_popCopyReg(&pic16_pc_fsr0l)));
630 // pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_fsr2h), pic16_popCopyReg(&pic16_pc_fsr0h)));
633 /* initialise for stack access via frame pointer */
634 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
636 // pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
637 // pic16_popCopyReg(&pic16_pc_plusw2), pic16_popCopyReg(&pic16_pc_kzero)));
640 // pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
647 /* now assign the address of the variable to
648 the pointer register */
649 if (aop->type != AOP_STK) {
653 pic16_emitcode("push","acc");
655 pic16_emitcode("mov","a,_bp");
656 pic16_emitcode("add","a,#0x%02x",
658 ((char)(sym->stack - _G.nRegsSaved )) :
659 ((char)sym->stack)) & 0xff);
660 pic16_emitcode("mov","%s,a",
661 aop->aopu.aop_ptr->name);
664 pic16_emitcode("pop","acc");
666 pic16_emitcode("mov","%s,#%s",
667 aop->aopu.aop_ptr->name,
669 aop->paged = space->paged;
671 aop->aopu.aop_stk = sym->stack;
679 if (sym->onStack && options.stack10bit)
681 /* It's on the 10 bit stack, which is located in
685 //DEBUGpic16_emitcode(";","%d",__LINE__);
688 pic16_emitcode("push","acc");
690 pic16_emitcode("mov","a,_bp");
691 pic16_emitcode("add","a,#0x%02x",
693 ((char)(sym->stack - _G.nRegsSaved )) :
694 ((char)sym->stack)) & 0xff);
697 pic16_emitcode ("mov","dpx1,#0x40");
698 pic16_emitcode ("mov","dph1,#0x00");
699 pic16_emitcode ("mov","dpl1, a");
703 pic16_emitcode("pop","acc");
705 sym->aop = aop = newAsmop(AOP_DPTR2);
706 aop->size = getSize(sym->type);
710 //DEBUGpic16_emitcode(";","%d",__LINE__);
711 /* if in bit space */
712 if (IN_BITSPACE(space)) {
713 sym->aop = aop = newAsmop (AOP_CRY);
714 aop->aopu.aop_dir = sym->rname ;
715 aop->size = getSize(sym->type);
716 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
719 /* if it is in direct space */
720 if (IN_DIRSPACE(space)) {
721 sym->aop = aop = newAsmop (AOP_DIR);
722 aop->aopu.aop_dir = sym->rname ;
723 aop->size = getSize(sym->type);
724 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
725 pic16_allocDirReg( IC_LEFT(ic) );
729 if (IN_FARSPACE(space)) {
730 sym->aop = aop = newAsmop (AOP_DIR);
731 aop->aopu.aop_dir = sym->rname ;
732 aop->size = getSize(sym->type);
733 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
734 pic16_allocDirReg( IC_LEFT(ic) );
739 /* special case for a function */
740 if (IS_FUNC(sym->type)) {
741 sym->aop = aop = newAsmop(AOP_IMMD);
742 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
743 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
744 strcpy(aop->aopu.aop_immd,sym->rname);
745 aop->size = FPTRSIZE;
746 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
752 /* only remaining is far space */
753 /* in which case DPTR gets the address */
754 sym->aop = aop = newAsmop(AOP_PCODE);
756 /* change the next if to 1 to revert to good old immediate code */
757 if(IN_CODESPACE(space)) {
758 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
759 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
760 PCOI(aop->aopu.pcop)->index = 0;
762 /* try to allocate via direct register */
763 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
764 // aop->size = getSize( sym->type );
767 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
768 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
771 if(!pic16_allocDirReg (IC_LEFT(ic)))
775 if(IN_DIRSPACE( space ))
777 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
778 aop->size = FPTRSIZE;
779 else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
780 else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
785 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
787 /* if it is in code space */
788 if (IN_CODESPACE(space))
794 /*-----------------------------------------------------------------*/
795 /* aopForRemat - rematerialzes an object */
796 /*-----------------------------------------------------------------*/
797 static asmop *aopForRemat (operand *op) // x symbol *sym)
799 symbol *sym = OP_SYMBOL(op);
800 iCode *ic = NULL, *oldic;
801 asmop *aop = newAsmop(AOP_PCODE);
807 ic = sym->rematiCode;
809 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
811 if(IS_OP_POINTER(op)) {
812 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
818 // pic16_emitpcomment("ic: %s\n", printILine(ic));
821 val += (int) operandLitValue(IC_RIGHT(ic));
822 } else if (ic->op == '-') {
823 val -= (int) operandLitValue(IC_RIGHT(ic));
827 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
830 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
832 if(!op->isaddr)viaimmd++; else viaimmd=0;
834 /* set the following if to 1 to revert to good old immediate code */
835 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
838 DEBUGpic16_emitcode("%s:%d immediate", __FILE__, __LINE__);
840 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
843 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
845 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
848 PCOI(aop->aopu.pcop)->index = val;
850 DEBUGpic16_emitcode("%s:%d dir", __FILE__, __LINE__);
852 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
853 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
854 // aop->size = AOP_SIZE( IC_LEFT(ic) );
858 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
859 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
861 val, IS_PTR_CONST(operandType(op)));
863 val, IS_CODEPTR(operandType(op)));
866 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
868 pic16_allocDirReg (IC_LEFT(ic));
870 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
877 static int aopIdx (asmop *aop, int offset)
882 if(aop->type != AOP_REG)
885 return aop->aopu.aop_reg[offset]->rIdx;
890 /*-----------------------------------------------------------------*/
891 /* regsInCommon - two operands have some registers in common */
892 /*-----------------------------------------------------------------*/
893 static bool regsInCommon (operand *op1, operand *op2)
898 /* if they have registers in common */
899 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
902 sym1 = OP_SYMBOL(op1);
903 sym2 = OP_SYMBOL(op2);
905 if (sym1->nRegs == 0 || sym2->nRegs == 0)
908 for (i = 0 ; i < sym1->nRegs ; i++) {
913 for (j = 0 ; j < sym2->nRegs ;j++ ) {
917 if (sym2->regs[j] == sym1->regs[i])
925 /*-----------------------------------------------------------------*/
926 /* operandsEqu - equivalent */
927 /*-----------------------------------------------------------------*/
928 static bool operandsEqu ( operand *op1, operand *op2)
932 /* if they not symbols */
933 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
936 sym1 = OP_SYMBOL(op1);
937 sym2 = OP_SYMBOL(op2);
939 /* if both are itemps & one is spilt
940 and the other is not then false */
941 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
942 sym1->isspilt != sym2->isspilt )
945 /* if they are the same */
949 if (sym1->rname[0] && sym2->rname[0]
950 && strcmp (sym1->rname, sym2->rname) == 0)
954 /* if left is a tmp & right is not */
958 (sym1->usl.spillLoc == sym2))
965 (sym2->usl.spillLoc == sym1))
971 /*-----------------------------------------------------------------*/
972 /* pic16_sameRegs - two asmops have the same registers */
973 /*-----------------------------------------------------------------*/
974 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
981 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
982 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
984 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
986 if (aop1->type != AOP_REG ||
987 aop2->type != AOP_REG )
990 if (aop1->size != aop2->size )
993 for (i = 0 ; i < aop1->size ; i++ )
994 if (aop1->aopu.aop_reg[i] !=
995 aop2->aopu.aop_reg[i] )
1001 /*-----------------------------------------------------------------*/
1002 /* pic16_aopOp - allocates an asmop for an operand : */
1003 /*-----------------------------------------------------------------*/
1004 void pic16_aopOp (operand *op, iCode *ic, bool result)
1013 // DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1015 /* if this a literal */
1016 if (IS_OP_LITERAL(op)) {
1017 op->aop = aop = newAsmop(AOP_LIT);
1018 aop->aopu.aop_lit = op->operand.valOperand;
1019 aop->size = getSize(operandType(op));
1024 sym_link *type = operandType(op);
1026 if(IS_PTR_CONST(type))
1028 if(IS_CODEPTR(type))
1030 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1033 /* if already has a asmop then continue */
1037 /* if the underlying symbol has a aop */
1038 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1039 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1040 op->aop = OP_SYMBOL(op)->aop;
1044 /* if this is a true symbol */
1045 if (IS_TRUE_SYMOP(op)) {
1046 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1047 op->aop = aopForSym(ic, op, result);
1051 /* this is a temporary : this has
1057 e) can be a return use only */
1059 sym = OP_SYMBOL(op);
1061 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
1062 /* if the type is a conditional */
1063 if (sym->regType == REG_CND) {
1064 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1069 /* if it is spilt then two situations
1071 b) has a spill location */
1072 if (sym->isspilt || sym->nRegs == 0) {
1074 DEBUGpic16_emitcode(";","%d",__LINE__);
1075 /* rematerialize it NOW */
1078 sym->aop = op->aop = aop =
1080 aop->size = getSize(sym->type);
1081 //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1088 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1089 aop->size = getSize(sym->type);
1090 for ( i = 0 ; i < 1 ; i++ ) {
1091 aop->aopu.aop_str[i] = accUse[i];
1092 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1094 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1095 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1103 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1104 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1105 //pic16_allocDirReg (IC_LEFT(ic));
1106 aop->size = getSize(sym->type);
1111 aop = op->aop = sym->aop = newAsmop(AOP_STR);
1112 aop->size = getSize(sym->type);
1113 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1114 aop->aopu.aop_str[i] = fReturn[i];
1116 DEBUGpic16_emitcode(";","%d",__LINE__);
1120 /* else spill location */
1121 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1122 /* force a new aop if sizes differ */
1123 sym->usl.spillLoc->aop = NULL;
1125 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1126 __FUNCTION__,__LINE__,
1127 sym->usl.spillLoc->rname,
1128 sym->rname, sym->usl.spillLoc->offset);
1130 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1131 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1132 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1134 sym->usl.spillLoc->offset, op);
1135 aop->size = getSize(sym->type);
1141 sym_link *type = operandType(op);
1143 if(IS_PTR_CONST(type))
1145 if(IS_CODEPTR(type))
1147 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1150 /* must be in a register */
1151 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1152 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1153 aop->size = sym->nRegs;
1154 for ( i = 0 ; i < sym->nRegs ;i++)
1155 aop->aopu.aop_reg[i] = sym->regs[i];
1158 /*-----------------------------------------------------------------*/
1159 /* pic16_freeAsmop - free up the asmop given to an operand */
1160 /*----------------------------------------------------------------*/
1161 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1178 /* depending on the asmop type only three cases need work AOP_RO
1179 , AOP_R1 && AOP_STK */
1181 switch (aop->type) {
1183 if (_G.fsr0Pushed ) {
1185 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1186 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1187 // pic16_emitcode ("pop","ar0");
1191 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1195 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1201 pic16_emitcode ("pop","ar0");
1205 bitVectUnSetBit(ic->rUsed,R0_IDX);
1211 pic16_emitcode ("pop","ar1");
1215 bitVectUnSetBit(ic->rUsed,R1_IDX);
1221 int stk = aop->aopu.aop_stk + aop->size;
1222 bitVectUnSetBit(ic->rUsed,R0_IDX);
1223 bitVectUnSetBit(ic->rUsed,R1_IDX);
1225 getFreePtr(ic,&aop,FALSE);
1227 if (options.stack10bit)
1229 /* I'm not sure what to do here yet... */
1232 "*** Warning: probably generating bad code for "
1233 "10 bit stack mode.\n");
1237 pic16_emitcode ("mov","a,_bp");
1238 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1239 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1241 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1245 pic16_emitcode("pop","acc");
1246 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1248 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1251 pic16_freeAsmop(op,NULL,ic,TRUE);
1253 pic16_emitcode("pop","ar0");
1258 pic16_emitcode("pop","ar1");
1266 /* all other cases just dealloc */
1270 OP_SYMBOL(op)->aop = NULL;
1271 /* if the symbol has a spill */
1273 SPIL_LOC(op)->aop = NULL;
1278 /*-----------------------------------------------------------------*/
1279 /* pic16_aopGet - for fetching value of the aop */
1280 /*-----------------------------------------------------------------*/
1281 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1286 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1288 /* offset is greater than size then zero */
1289 if (offset > (aop->size - 1) &&
1290 aop->type != AOP_LIT)
1293 /* depending on type */
1294 switch (aop->type) {
1298 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1299 rs = Safe_calloc(1, strlen(s)+1);
1304 /* if we need to increment it */
1305 while (offset > aop->coff)
1307 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1311 while (offset < aop->coff)
1313 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1319 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1320 return (dname ? "acc" : "a");
1322 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1323 rs = Safe_calloc (1, strlen (s) + 1);
1331 sprintf (s,"%s",aop->aopu.aop_immd);
1334 sprintf(s,"(%s >> %d)",
1339 aop->aopu.aop_immd);
1340 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1341 rs = Safe_calloc(1,strlen(s)+1);
1347 sprintf(s,"(%s + %d)",
1350 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1352 sprintf(s,"%s",aop->aopu.aop_dir);
1353 rs = Safe_calloc(1,strlen(s)+1);
1359 // return aop->aopu.aop_reg[offset]->dname;
1361 return aop->aopu.aop_reg[offset]->name;
1364 //pic16_emitcode(";","%d",__LINE__);
1365 return aop->aopu.aop_dir;
1368 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1369 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1371 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1372 rs = Safe_strdup("WREG");
1376 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1377 rs = Safe_calloc(1,strlen(s)+1);
1382 aop->coff = offset ;
1383 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1386 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1388 return aop->aopu.aop_str[offset];
1392 pCodeOp *pcop = aop->aopu.pcop;
1393 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1395 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1396 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1397 sprintf(s,"%s", pcop->name);
1399 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1402 rs = Safe_calloc(1,strlen(s)+1);
1407 // pCodeOp *pcop = aop->aop
1412 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1413 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1414 "aopget got unsupported aop->type");
1419 /*-----------------------------------------------------------------*/
1420 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1421 /*-----------------------------------------------------------------*/
1422 pCodeOp *pic16_popGetTempReg(void)
1427 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1432 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1433 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1434 PCOR(pcop)->r->wasUsed=1;
1435 PCOR(pcop)->r->isFree=0;
1437 /* push value on stack */
1438 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1446 /*-----------------------------------------------------------------*/
1447 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1448 /*-----------------------------------------------------------------*/
1449 void pic16_popReleaseTempReg(pCodeOp *pcop)
1451 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1453 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1454 PCOR(pcop)->r->isFree = 1;
1456 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1459 /*-----------------------------------------------------------------*/
1460 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1461 /*-----------------------------------------------------------------*/
1462 pCodeOp *pic16_popGetLabel(unsigned int key)
1465 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1470 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1473 /*-----------------------------------------------------------------*/
1474 /* pic16_popCopyReg - copy a pcode operator */
1475 /*-----------------------------------------------------------------*/
1476 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1480 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1481 pcor->pcop.type = pc->pcop.type;
1483 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1484 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1486 pcor->pcop.name = NULL;
1489 pcor->rIdx = pc->rIdx;
1492 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1497 /*-----------------------------------------------------------------*/
1498 /* pic16_popGetLit - asm operator to pcode operator conversion */
1499 /*-----------------------------------------------------------------*/
1500 pCodeOp *pic16_popGetLit(unsigned int lit)
1502 return pic16_newpCodeOpLit(lit);
1505 /*-----------------------------------------------------------------*/
1506 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1507 /*-----------------------------------------------------------------*/
1508 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1510 return pic16_newpCodeOpLit2(lit, arg2);
1514 /*-----------------------------------------------------------------*/
1515 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1516 /*-----------------------------------------------------------------*/
1517 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1519 return pic16_newpCodeOpImmd(name, offset,index, 0);
1523 /*-----------------------------------------------------------------*/
1524 /* pic16_popGet - asm operator to pcode operator conversion */
1525 /*-----------------------------------------------------------------*/
1526 pCodeOp *pic16_popGetWithString(char *str)
1532 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1536 pcop = pic16_newpCodeOp(str,PO_STR);
1541 /*-----------------------------------------------------------------*/
1542 /* pic16_popRegFromString - */
1543 /*-----------------------------------------------------------------*/
1544 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1547 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1548 pcop->type = PO_DIR;
1550 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1551 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1556 pcop->name = Safe_calloc(1,strlen(str)+1);
1557 strcpy(pcop->name,str);
1559 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1561 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1562 if(PCOR(pcop)->r == NULL) {
1563 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1564 // __FUNCTION__, __LINE__, str, size, offset);
1567 // PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1568 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1570 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1572 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d",__LINE__,pcop->name,size,offset);
1574 PCOR(pcop)->instance = offset;
1579 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1583 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1585 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1586 PCOR(pcop)->rIdx = rIdx;
1587 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1589 PCOR(pcop)->r->isFree = 0;
1590 PCOR(pcop)->r->wasUsed = 1;
1592 pcop->type = PCOR(pcop)->r->pc_type;
1597 /*---------------------------------------------------------------------------------*/
1598 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1600 /*---------------------------------------------------------------------------------*/
1601 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1606 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1608 /* comment the following check, so errors to throw up */
1609 // if(!pcop2)return NULL;
1611 temp = pic16_popGet(aop_dst, offset);
1612 pcop2->pcop2 = temp;
1619 /*--------------------------------------------------------------------------------.-*/
1620 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1621 /* VR 030601 , adapted by Hans Dorn */
1622 /*--------------------------------------------------------------------------------.-*/
1623 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1627 pcop2 = (pCodeOpReg2 *)src;
1635 /*---------------------------------------------------------------------------------*/
1636 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1637 /* movff instruction */
1638 /*---------------------------------------------------------------------------------*/
1639 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1644 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1645 pcop2->pcop2 = pic16_popCopyReg(dst);
1647 /* the pCodeOp may be already allocated */
1648 pcop2 = (pCodeOpReg2 *)(src);
1649 pcop2->pcop2 = (pCodeOp *)(dst);
1656 /*-----------------------------------------------------------------*/
1657 /* pic16_popGet - asm operator to pcode operator conversion */
1658 /*-----------------------------------------------------------------*/
1659 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1661 //char *s = buffer ;
1665 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1666 /* offset is greater than
1669 // if (offset > (aop->size - 1) &&
1670 // aop->type != AOP_LIT)
1671 // return NULL; //zero;
1673 /* depending on type */
1674 switch (aop->type) {
1680 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1681 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1688 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1689 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
1690 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1691 PCOR(pcop)->r->wasUsed = 1;
1692 PCOR(pcop)->r->isFree = 0;
1694 PCOR(pcop)->instance = offset;
1695 pcop->type = PCOR(pcop)->r->pc_type;
1699 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1700 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1704 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1706 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1708 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1710 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1711 PCOR(pcop)->rIdx = rIdx;
1712 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1713 PCOR(pcop)->r->wasUsed=1;
1714 PCOR(pcop)->r->isFree=0;
1716 PCOR(pcop)->instance = offset;
1717 pcop->type = PCOR(pcop)->r->pc_type;
1718 // rs = aop->aopu.aop_reg[offset]->name;
1719 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1723 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1724 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1730 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1731 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1735 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1737 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1739 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1740 // pcop->type = PO_GPR_REGISTER;
1741 PCOR(pcop)->rIdx = rIdx;
1742 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
1743 PCOR(pcop)->r->wasUsed=1;
1744 PCOR(pcop)->r->isFree=0;
1746 PCOR(pcop)->instance = offset;
1747 pcop->type = PCOR(pcop)->r->pc_type;
1748 rs = aop->aopu.aop_reg[offset]->name;
1749 DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1754 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1756 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1757 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1758 //if(PCOR(pcop)->r == NULL)
1759 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1763 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1764 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1767 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1768 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1771 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1772 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1773 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1774 pcop->type = PCOR(pcop)->r->pc_type;
1775 pcop->name = PCOR(pcop)->r->name;
1781 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1783 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1784 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1786 switch( aop->aopu.pcop->type ) {
1787 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1788 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1790 assert( 0 ); /* should never reach here */;
1793 PCOI(pcop)->offset = offset;
1798 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1799 "pic16_popGet got unsupported aop->type");
1802 /*-----------------------------------------------------------------*/
1803 /* pic16_aopPut - puts a string for a aop */
1804 /*-----------------------------------------------------------------*/
1805 void pic16_aopPut (asmop *aop, char *s, int offset)
1810 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1812 if (aop->size && offset > ( aop->size - 1)) {
1813 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1814 "pic16_aopPut got offset > aop->size");
1818 /* will assign value to value */
1819 /* depending on where it is ofcourse */
1820 switch (aop->type) {
1823 sprintf(d,"(%s + %d)",
1824 aop->aopu.aop_dir,offset);
1825 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1828 sprintf(d,"%s",aop->aopu.aop_dir);
1831 DEBUGpic16_emitcode(";","%d",__LINE__);
1833 pic16_emitcode("movf","%s,w",s);
1834 pic16_emitcode("movwf","%s",d);
1837 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1838 if(offset >= aop->size) {
1839 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1842 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1845 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1852 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1853 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1856 strcmp(s,"r0") == 0 ||
1857 strcmp(s,"r1") == 0 ||
1858 strcmp(s,"r2") == 0 ||
1859 strcmp(s,"r3") == 0 ||
1860 strcmp(s,"r4") == 0 ||
1861 strcmp(s,"r5") == 0 ||
1862 strcmp(s,"r6") == 0 ||
1863 strcmp(s,"r7") == 0 )
1864 pic16_emitcode("mov","%s,%s ; %d",
1865 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1869 if(strcmp(s,"W")==0 )
1870 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
1872 pic16_emitcode("movwf","%s",
1873 aop->aopu.aop_reg[offset]->name);
1875 if(strcmp(s,zero)==0) {
1876 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1878 } else if(strcmp(s,"W")==0) {
1879 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1880 pcop->type = PO_GPR_REGISTER;
1882 PCOR(pcop)->rIdx = -1;
1883 PCOR(pcop)->r = NULL;
1885 DEBUGpic16_emitcode(";","%d",__LINE__);
1886 pcop->name = Safe_strdup(s);
1887 pic16_emitpcode(POC_MOVFW,pcop);
1888 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1889 } else if(strcmp(s,one)==0) {
1890 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1891 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1893 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1901 if (aop->type == AOP_DPTR2)
1907 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1908 "pic16_aopPut writting to code space");
1912 while (offset > aop->coff) {
1914 pic16_emitcode ("inc","dptr");
1917 while (offset < aop->coff) {
1919 pic16_emitcode("lcall","__decdptr");
1924 /* if not in accumulater */
1927 pic16_emitcode ("movx","@dptr,a");
1929 if (aop->type == AOP_DPTR2)
1937 while (offset > aop->coff) {
1939 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1941 while (offset < aop->coff) {
1943 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1949 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1954 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1956 if (strcmp(s,"r0") == 0 ||
1957 strcmp(s,"r1") == 0 ||
1958 strcmp(s,"r2") == 0 ||
1959 strcmp(s,"r3") == 0 ||
1960 strcmp(s,"r4") == 0 ||
1961 strcmp(s,"r5") == 0 ||
1962 strcmp(s,"r6") == 0 ||
1963 strcmp(s,"r7") == 0 ) {
1965 sprintf(buffer,"a%s",s);
1966 pic16_emitcode("mov","@%s,%s",
1967 aop->aopu.aop_ptr->name,buffer);
1969 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1974 if (strcmp(s,"a") == 0)
1975 pic16_emitcode("push","acc");
1977 pic16_emitcode("push","%s",s);
1982 /* if bit variable */
1983 if (!aop->aopu.aop_dir) {
1984 pic16_emitcode("clr","a");
1985 pic16_emitcode("rlc","a");
1988 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1991 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1994 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1996 lbl = newiTempLabel(NULL);
1998 if (strcmp(s,"a")) {
2001 pic16_emitcode("clr","c");
2002 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2003 pic16_emitcode("cpl","c");
2004 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2005 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2012 if (strcmp(aop->aopu.aop_str[offset],s))
2013 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2018 if (!offset && (strcmp(s,"acc") == 0))
2021 if (strcmp(aop->aopu.aop_str[offset],s))
2022 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2026 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2027 "pic16_aopPut got unsupported aop->type");
2033 /*-----------------------------------------------------------------*/
2034 /* mov2w - generate either a MOVLW or MOVFW based operand type */
2035 /*-----------------------------------------------------------------*/
2036 static void mov2w (asmop *aop, int offset)
2042 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2045 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2047 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2052 /* push pcop into stack */
2053 void pic16_pushpCodeOp(pCodeOp *pcop)
2055 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2056 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2059 /* pop pcop from stack */
2060 void pic16_poppCodeOp(pCodeOp *pcop)
2062 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2066 /*-----------------------------------------------------------------*/
2067 /* pushw - pushes wreg to stack */
2068 /*-----------------------------------------------------------------*/
2071 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2072 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2076 /*-----------------------------------------------------------------*/
2077 /* pushaop - pushes aop to stack */
2078 /*-----------------------------------------------------------------*/
2079 void pushaop(asmop *aop, int offset)
2081 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2082 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2085 /*-----------------------------------------------------------------*/
2086 /* popaop - pops aop from stack */
2087 /*-----------------------------------------------------------------*/
2088 void popaop(asmop *aop, int offset)
2090 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2091 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2094 void popaopidx(asmop *aop, int offset, int index)
2098 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2100 if(STACK_MODEL_LARGE)ofs++;
2102 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2103 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2106 /*-----------------------------------------------------------------*/
2107 /* reAdjustPreg - points a register back to where it should */
2108 /*-----------------------------------------------------------------*/
2109 static void reAdjustPreg (asmop *aop)
2113 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2115 if ((size = aop->size) <= 1)
2118 switch (aop->type) {
2122 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2126 if (aop->type == AOP_DPTR2)
2132 pic16_emitcode("lcall","__decdptr");
2135 if (aop->type == AOP_DPTR2)
2147 /*-----------------------------------------------------------------*/
2148 /* opIsGptr: returns non-zero if the passed operand is */
2149 /* a generic pointer type. */
2150 /*-----------------------------------------------------------------*/
2151 static int opIsGptr(operand *op)
2153 sym_link *type = operandType(op);
2155 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2156 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2164 /*-----------------------------------------------------------------*/
2165 /* pic16_getDataSize - get the operand data size */
2166 /*-----------------------------------------------------------------*/
2167 int pic16_getDataSize(operand *op)
2169 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2172 return AOP_SIZE(op);
2174 // tsd- in the pic port, the genptr size is 1, so this code here
2175 // fails. ( in the 8051 port, the size was 4).
2178 size = AOP_SIZE(op);
2179 if (size == GPTRSIZE)
2181 sym_link *type = operandType(op);
2182 if (IS_GENPTR(type))
2184 /* generic pointer; arithmetic operations
2185 * should ignore the high byte (pointer type).
2188 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2195 /*-----------------------------------------------------------------*/
2196 /* pic16_outAcc - output Acc */
2197 /*-----------------------------------------------------------------*/
2198 void pic16_outAcc(operand *result)
2201 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2202 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2205 size = pic16_getDataSize(result);
2207 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2210 /* unsigned or positive */
2212 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2217 /*-----------------------------------------------------------------*/
2218 /* pic16_outBitC - output a bit C */
2219 /* Move to result the value of Carry flag -- VR */
2220 /*-----------------------------------------------------------------*/
2221 void pic16_outBitC(operand *result)
2225 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2226 /* if the result is bit */
2227 if (AOP_TYPE(result) == AOP_CRY) {
2228 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2229 pic16_aopPut(AOP(result),"c",0);
2232 i = AOP_SIZE(result);
2234 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2236 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2239 pic16_emitcode("clr","a ; %d", __LINE__);
2240 pic16_emitcode("rlc","a");
2241 pic16_outAcc(result);
2246 /*-----------------------------------------------------------------*/
2247 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2248 /*-----------------------------------------------------------------*/
2249 void pic16_toBoolean(operand *oper)
2251 int size = AOP_SIZE(oper) - 1;
2254 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2256 if ( AOP_TYPE(oper) != AOP_ACC) {
2257 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2260 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2265 #if !defined(GEN_Not)
2266 /*-----------------------------------------------------------------*/
2267 /* genNot - generate code for ! operation */
2268 /*-----------------------------------------------------------------*/
2269 static void pic16_genNot (iCode *ic)
2274 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2275 /* assign asmOps to operand & result */
2276 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2277 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2279 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2280 /* if in bit space then a special case */
2281 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2282 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2283 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2284 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2286 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2287 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2288 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2293 size = AOP_SIZE(IC_LEFT(ic));
2295 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2296 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2297 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2300 pic16_toBoolean(IC_LEFT(ic));
2302 tlbl = newiTempLabel(NULL);
2303 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2304 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2305 pic16_outBitC(IC_RESULT(ic));
2308 /* release the aops */
2309 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2310 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2315 #if !defined(GEN_Cpl)
2316 /*-----------------------------------------------------------------*/
2317 /* genCpl - generate code for complement */
2318 /*-----------------------------------------------------------------*/
2319 static void pic16_genCpl (iCode *ic)
2325 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2326 /* assign asmOps to operand & result */
2327 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2328 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2330 /* if both are in bit space then
2332 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2333 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2335 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2336 pic16_emitcode("cpl","c");
2337 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2341 size = AOP_SIZE(IC_RESULT(ic));
2344 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2346 pic16_emitcode("cpl","a");
2347 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2349 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2350 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2352 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2353 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2361 /* release the aops */
2362 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2363 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2367 /*-----------------------------------------------------------------*/
2368 /* genUminusFloat - unary minus for floating points */
2369 /*-----------------------------------------------------------------*/
2370 static void genUminusFloat(operand *op,operand *result)
2372 int size ,offset =0 ;
2375 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2376 /* for this we just need to flip the
2377 first it then copy the rest in place */
2378 size = AOP_SIZE(op) - 1;
2379 l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2383 pic16_emitcode("cpl","acc.7");
2384 pic16_aopPut(AOP(result),"a",3);
2387 pic16_aopPut(AOP(result),
2388 pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2394 /*-----------------------------------------------------------------*/
2395 /* genUminus - unary minus code generation */
2396 /*-----------------------------------------------------------------*/
2397 static void genUminus (iCode *ic)
2400 sym_link *optype, *rtype;
2402 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2405 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2406 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2408 /* if both in bit space then special case */
2409 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2410 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2412 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2413 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2414 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2419 optype = operandType(IC_LEFT(ic));
2420 rtype = operandType(IC_RESULT(ic));
2422 /* if float then do float stuff */
2423 if (IS_FLOAT(optype)) {
2424 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2428 /* otherwise subtract from zero by taking the 2's complement */
2429 size = AOP_SIZE(IC_LEFT(ic));
2431 for(i=0; i<size; i++) {
2432 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2433 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)),i));
2435 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2436 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2440 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2441 for(i=1; i<size; i++) {
2443 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2447 /* release the aops */
2448 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2449 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2452 /*-----------------------------------------------------------------*/
2453 /* saveRegisters - will look for a call and save the registers */
2454 /*-----------------------------------------------------------------*/
2455 static void saveRegisters(iCode *lic)
2462 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2464 for (ic = lic ; ic ; ic = ic->next)
2465 if (ic->op == CALL || ic->op == PCALL)
2469 fprintf(stderr,"found parameter push with no function call\n");
2473 /* if the registers have been saved already then
2475 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2478 /* find the registers in use at this time
2479 and push them away to safety */
2480 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2484 if (options.useXstack) {
2485 if (bitVectBitValue(rsave,R0_IDX))
2486 pic16_emitcode("mov","b,r0");
2487 pic16_emitcode("mov","r0,%s",spname);
2488 for (i = 0 ; i < pic16_nRegs ; i++) {
2489 if (bitVectBitValue(rsave,i)) {
2491 pic16_emitcode("mov","a,b");
2493 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2494 pic16_emitcode("movx","@r0,a");
2495 pic16_emitcode("inc","r0");
2498 pic16_emitcode("mov","%s,r0",spname);
2499 if (bitVectBitValue(rsave,R0_IDX))
2500 pic16_emitcode("mov","r0,b");
2502 //for (i = 0 ; i < pic16_nRegs ; i++) {
2503 // if (bitVectBitValue(rsave,i))
2504 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2507 dtype = operandType(IC_LEFT(ic));
2508 if (currFunc && dtype &&
2509 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2510 IFFUNC_ISISR(currFunc->type) &&
2513 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2516 /*-----------------------------------------------------------------*/
2517 /* unsaveRegisters - pop the pushed registers */
2518 /*-----------------------------------------------------------------*/
2519 static void unsaveRegisters (iCode *ic)
2524 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2525 /* find the registers in use at this time
2526 and push them away to safety */
2527 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2530 if (options.useXstack) {
2531 pic16_emitcode("mov","r0,%s",spname);
2532 for (i = pic16_nRegs ; i >= 0 ; i--) {
2533 if (bitVectBitValue(rsave,i)) {
2534 pic16_emitcode("dec","r0");
2535 pic16_emitcode("movx","a,@r0");
2537 pic16_emitcode("mov","b,a");
2539 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2543 pic16_emitcode("mov","%s,r0",spname);
2544 if (bitVectBitValue(rsave,R0_IDX))
2545 pic16_emitcode("mov","r0,b");
2547 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2548 // if (bitVectBitValue(rsave,i))
2549 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2555 /*-----------------------------------------------------------------*/
2557 /*-----------------------------------------------------------------*/
2558 static void pushSide(operand * oper, int size)
2561 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2563 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2564 if (AOP_TYPE(oper) != AOP_REG &&
2565 AOP_TYPE(oper) != AOP_DIR &&
2567 pic16_emitcode("mov","a,%s",l);
2568 pic16_emitcode("push","acc");
2570 pic16_emitcode("push","%s",l);
2575 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2577 // (AOP(left)->aopu.pcop->type == PO_DIR)?
2579 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2580 pic16_emitpcode(POC_MOVFW, src);
2581 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2583 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2584 src, pic16_popGet(AOP(op), offset)));
2589 /*-----------------------------------------------------------------*/
2590 /* assignResultValue - assign results to oper, rescall==1 is */
2591 /* called from genCall() or genPCall() */
2592 /*-----------------------------------------------------------------*/
2593 static void assignResultValue(operand * oper, int rescall)
2595 int size = AOP_SIZE(oper);
2597 DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2598 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2601 /* assign result from a call/pcall function() */
2603 /* function results are stored in a special order,
2604 * see top of file with Function return policy, or manual */
2607 /* 8-bits, result in WREG */
2608 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2611 /* 16-bits, result in PRODL:WREG */
2612 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2616 /* 24-bits, result in PRODH:PRODL:WREG */
2617 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2621 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2622 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2625 /* >32-bits, result on stack, and FSR0 points to beginning.
2626 * Fix stack when done */
2629 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2630 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2632 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2637 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2638 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2639 if(STACK_MODEL_LARGE) {
2641 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2645 if(!GpsuedoStkPtr) {
2646 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2647 /* The last byte in the assignment is in W */
2649 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2654 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2655 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2657 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2663 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2665 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2675 /*-----------------------------------------------------------------*/
2676 /* genIpush - genrate code for pushing this gets a little complex */
2677 /*-----------------------------------------------------------------*/
2678 static void genIpush (iCode *ic)
2682 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2685 pic16_aopOp(IC_LEFT(ic), ic, FALSE);
2688 size = AOP_SIZE( IC_LEFT(ic) );
2691 mov2w( AOP(IC_LEFT(ic)), offset );
2697 int size, offset = 0 ;
2701 /* if this is not a parm push : ie. it is spill push
2702 and spill push is always done on the local stack */
2703 if (!ic->parmPush) {
2705 /* and the item is spilt then do nothing */
2706 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2709 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2710 size = AOP_SIZE(IC_LEFT(ic));
2711 /* push it on the stack */
2713 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2718 pic16_emitcode("push","%s",l);
2723 /* this is a paramter push: in this case we call
2724 the routine to find the call and save those
2725 registers that need to be saved */
2728 /* then do the push */
2729 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2732 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2733 size = AOP_SIZE(IC_LEFT(ic));
2736 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2737 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2738 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2740 pic16_emitcode("mov","a,%s",l);
2741 pic16_emitcode("push","acc");
2743 pic16_emitcode("push","%s",l);
2746 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2750 /*-----------------------------------------------------------------*/
2751 /* genIpop - recover the registers: can happen only for spilling */
2752 /*-----------------------------------------------------------------*/
2753 static void genIpop (iCode *ic)
2755 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2760 /* if the temp was not pushed then */
2761 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2764 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2765 size = AOP_SIZE(IC_LEFT(ic));
2768 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2771 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2775 /*-----------------------------------------------------------------*/
2776 /* unsaverbank - restores the resgister bank from stack */
2777 /*-----------------------------------------------------------------*/
2778 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2780 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2786 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2788 if (options.useXstack) {
2790 r = getFreePtr(ic,&aop,FALSE);
2793 pic16_emitcode("mov","%s,_spx",r->name);
2794 pic16_emitcode("movx","a,@%s",r->name);
2795 pic16_emitcode("mov","psw,a");
2796 pic16_emitcode("dec","%s",r->name);
2799 pic16_emitcode ("pop","psw");
2802 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2803 if (options.useXstack) {
2804 pic16_emitcode("movx","a,@%s",r->name);
2805 //pic16_emitcode("mov","(%s+%d),a",
2806 // regspic16[i].base,8*bank+regspic16[i].offset);
2807 pic16_emitcode("dec","%s",r->name);
2810 pic16_emitcode("pop",""); //"(%s+%d)",
2811 //regspic16[i].base,8*bank); //+regspic16[i].offset);
2814 if (options.useXstack) {
2816 pic16_emitcode("mov","_spx,%s",r->name);
2817 pic16_freeAsmop(NULL,aop,ic,TRUE);
2823 /*-----------------------------------------------------------------*/
2824 /* saverbank - saves an entire register bank on the stack */
2825 /*-----------------------------------------------------------------*/
2826 static void saverbank (int bank, iCode *ic, bool pushPsw)
2828 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2834 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2835 if (options.useXstack) {
2838 r = getFreePtr(ic,&aop,FALSE);
2839 pic16_emitcode("mov","%s,_spx",r->name);
2843 for (i = 0 ; i < pic16_nRegs ;i++) {
2844 if (options.useXstack) {
2845 pic16_emitcode("inc","%s",r->name);
2846 //pic16_emitcode("mov","a,(%s+%d)",
2847 // regspic16[i].base,8*bank+regspic16[i].offset);
2848 pic16_emitcode("movx","@%s,a",r->name);
2850 pic16_emitcode("push","");// "(%s+%d)",
2851 //regspic16[i].base,8*bank+regspic16[i].offset);
2855 if (options.useXstack) {
2856 pic16_emitcode("mov","a,psw");
2857 pic16_emitcode("movx","@%s,a",r->name);
2858 pic16_emitcode("inc","%s",r->name);
2859 pic16_emitcode("mov","_spx,%s",r->name);
2860 pic16_freeAsmop (NULL,aop,ic,TRUE);
2863 pic16_emitcode("push","psw");
2865 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2873 /*-----------------------------------------------------------------*/
2874 /* genCall - generates a call statement */
2875 /*-----------------------------------------------------------------*/
2876 static void genCall (iCode *ic)
2881 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2883 /* if caller saves & we have not saved then */
2887 /* if we are calling a function that is not using
2888 * the same register bank then we need to save the
2889 * destination registers on the stack */
2890 dtype = operandType(IC_LEFT(ic));
2891 if (currFunc && dtype &&
2892 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2893 IFFUNC_ISISR(currFunc->type) &&
2896 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2899 /* initialise stackParms for IPUSH pushes */
2900 // stackParms = psuedoStkPtr;
2901 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2903 /* if send set is not empty the assign */
2907 /* For the Pic port, there is no data stack.
2908 * So parameters passed to functions are stored
2909 * in registers. (The pCode optimizer will get
2910 * rid of most of these :). */
2912 int psuedoStkPtr=-1;
2913 int firstTimeThruLoop = 1;
2915 _G.sendSet = reverseSet(_G.sendSet);
2917 /* First figure how many parameters are getting passed */
2918 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2919 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2920 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2921 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2924 stackParms = psuedoStkPtr;
2926 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2927 int size, offset = 0;
2929 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2930 size = AOP_SIZE(IC_LEFT(sic));
2933 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2934 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2935 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2937 if(!firstTimeThruLoop) {
2938 /* If this is not the first time we've been through the loop
2939 * then we need to save the parameter in a temporary
2940 * register. The last byte of the last parameter is
2944 --psuedoStkPtr; // sanity check
2947 firstTimeThruLoop=0;
2949 mov2w (AOP(IC_LEFT(sic)), offset);
2952 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2958 pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2959 OP_SYMBOL(IC_LEFT(ic))->rname :
2960 OP_SYMBOL(IC_LEFT(ic))->name));
2963 /* if we need assign a result value */
2964 if ((IS_ITEMP(IC_RESULT(ic)) &&
2965 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2966 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2967 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2970 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2973 assignResultValue(IC_RESULT(ic), 1);
2975 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2976 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2978 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2981 if(!stackParms && ic->parmBytes) {
2982 stackParms = ic->parmBytes;
2986 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2987 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2988 if(STACK_MODEL_LARGE) {
2990 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2994 /* adjust the stack for parameters if required */
2995 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2997 if (ic->parmBytes) {
3000 if (ic->parmBytes > 3) {
3001 pic16_emitcode("mov","a,%s",spname);
3002 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3003 pic16_emitcode("mov","%s,a",spname);
3005 for ( i = 0 ; i < ic->parmBytes ;i++)
3006 pic16_emitcode("dec","%s",spname);
3011 /* if register bank was saved then pop them */
3013 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3015 /* if we hade saved some registers then unsave them */
3016 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3017 unsaveRegisters (ic);
3023 /*-----------------------------------------------------------------*/ // patch 14
3024 /* genPcall - generates a call by pointer statement */
3025 /*-----------------------------------------------------------------*/
3027 // new version, created from genCall
3029 static void genPcall (iCode *ic)
3033 symbol *retlbl = newiTempLabel(NULL);
3034 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3036 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 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
3048 IFFUNC_ISISR(currFunc->type) &&
3051 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3053 /* if send set is not empty the assign */
3057 /* For the Pic port, there is no data stack.
3058 * So parameters passed to functions are stored
3059 * in registers. (The pCode optimizer will get
3060 * rid of most of these :). */
3062 int psuedoStkPtr=-1;
3063 int firstTimeThruLoop = 1;
3065 _G.sendSet = reverseSet(_G.sendSet);
3067 /* First figure how many parameters are getting passed */
3068 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3069 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3070 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
3071 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
3074 stackParms = psuedoStkPtr;
3076 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3077 int size, offset = 0;
3079 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3080 size = AOP_SIZE(IC_LEFT(sic));
3083 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3084 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3085 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3087 if(!firstTimeThruLoop) {
3088 /* If this is not the first time we've been through the loop
3089 * then we need to save the parameter in a temporary
3090 * register. The last byte of the last parameter is
3094 --psuedoStkPtr; // sanity check
3097 firstTimeThruLoop=0;
3099 mov2w (AOP(IC_LEFT(sic)), offset);
3102 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3107 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3109 // push return address
3110 // push $ on return stack, then replace with retlbl
3112 pic16_emitpcodeNULLop(POC_PUSH);
3114 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3115 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3116 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3117 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3118 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3119 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3121 /* make the call by writing the pointer into pc */
3122 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3123 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3125 // note: MOVFF to PCL not allowed
3126 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3127 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3130 // pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key));
3131 // pic16_emitpcodeNULLop(POC_NOP);
3132 // pic16_emitpcodeNULLop(POC_NOP);
3134 /* return address is here: (X) */
3135 pic16_emitpLabelFORCE(retlbl->key);
3137 // pic16_emitpcodeNULLop(POC_NOP);
3139 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3142 /* if we need assign a result value */
3143 if ((IS_ITEMP(IC_RESULT(ic)) &&
3144 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3145 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
3146 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3149 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3152 assignResultValue(IC_RESULT(ic), 1);
3154 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3155 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3157 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3161 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3162 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3163 if(STACK_MODEL_LARGE) {
3165 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3169 /* adjust the stack for parameters if required */
3170 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3172 if (ic->parmBytes) {
3175 if (ic->parmBytes > 3) {
3176 pic16_emitcode("mov","a,%s",spname);
3177 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3178 pic16_emitcode("mov","%s,a",spname);
3180 for ( i = 0 ; i < ic->parmBytes ;i++)
3181 pic16_emitcode("dec","%s",spname);
3184 /* if register bank was saved then pop them */
3186 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3188 /* if we hade saved some registers then unsave them */
3189 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3190 unsaveRegisters (ic);
3195 // old version, kept for reference
3197 /*-----------------------------------------------------------------*/
3198 /* genPcall - generates a call by pointer statement */
3199 /*-----------------------------------------------------------------*/
3200 static void genPcall (iCode *ic)
3203 symbol *rlbl = newiTempLabel(NULL);
3206 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3207 /* if caller saves & we have not saved then */
3211 /* if we are calling a function that is not using
3212 the same register bank then we need to save the
3213 destination registers on the stack */
3214 dtype = operandType(IC_LEFT(ic));
3215 if (currFunc && dtype &&
3216 IFFUNC_ISISR(currFunc->type) &&
3217 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3218 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3221 /* push the return address on to the stack */
3222 pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3223 pic16_emitcode("push","acc");
3224 pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3225 pic16_emitcode("push","acc");
3227 if (options.model == MODEL_FLAT24)
3229 pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3230 pic16_emitcode("push","acc");
3233 /* now push the calling address */
3234 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3236 pushSide(IC_LEFT(ic), FPTRSIZE);
3238 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3240 /* if send set is not empty the assign */
3244 for (sic = setFirstItem(_G.sendSet) ; sic ;
3245 sic = setNextItem(_G.sendSet)) {
3246 int size, offset = 0;
3247 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3248 size = AOP_SIZE(IC_LEFT(sic));
3250 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3252 if (strcmp(l,fReturn[offset]))
3253 pic16_emitcode("mov","%s,%s",
3258 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3263 pic16_emitcode("ret","");
3264 pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3267 /* if we need assign a result value */
3268 if ((IS_ITEMP(IC_RESULT(ic)) &&
3269 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3270 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3271 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3274 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3277 assignResultValue(IC_RESULT(ic), 1);
3279 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3282 /* adjust the stack for parameters if
3284 if (ic->parmBytes) {
3286 if (ic->parmBytes > 3) {
3287 pic16_emitcode("mov","a,%s",spname);
3288 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3289 pic16_emitcode("mov","%s,a",spname);
3291 for ( i = 0 ; i < ic->parmBytes ;i++)
3292 pic16_emitcode("dec","%s",spname);
3296 /* if register bank was saved then unsave them */
3297 if (currFunc && dtype &&
3298 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3299 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3301 /* if we hade saved some registers then
3304 unsaveRegisters (ic);
3310 /*-----------------------------------------------------------------*/
3311 /* resultRemat - result is rematerializable */
3312 /*-----------------------------------------------------------------*/
3313 static int resultRemat (iCode *ic)
3315 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3316 if (SKIP_IC(ic) || ic->op == IFX)
3319 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3320 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3321 if (sym->remat && !POINTER_SET(ic))
3328 #if defined(__BORLANDC__) || defined(_MSC_VER)
3329 #define STRCASECMP stricmp
3331 #define STRCASECMP strcasecmp
3335 /*-----------------------------------------------------------------*/
3336 /* inExcludeList - return 1 if the string is in exclude Reg list */
3337 /*-----------------------------------------------------------------*/
3338 static bool inExcludeList(char *s)
3340 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3343 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3344 if (options.excludeRegs[i] &&
3345 STRCASECMP(options.excludeRegs[i],"none") == 0)
3348 for ( i = 0 ; options.excludeRegs[i]; i++) {
3349 if (options.excludeRegs[i] &&
3350 STRCASECMP(s,options.excludeRegs[i]) == 0)
3357 /*-----------------------------------------------------------------*/
3358 /* genFunction - generated code for function entry */
3359 /*-----------------------------------------------------------------*/
3360 static void genFunction (iCode *ic)
3365 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3367 pic16_labelOffset += (max_key+4);
3372 ftype = operandType(IC_LEFT(ic));
3373 sym = OP_SYMBOL(IC_LEFT(ic));
3375 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3376 /* create an absolute section at the interrupt vector:
3377 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3385 sym = OP_SYMBOL( IC_LEFT(ic));
3387 if(interrupts[i]->name
3388 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3395 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3396 __FILE__, __LINE__, sym->name);
3399 _G.interruptvector = found;
3402 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3403 asym = newSymbol(asymname, 0);
3405 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3406 pic16_addpBlock( apb );
3408 pic16_addpCode2pBlock(apb,
3409 pic16_newpCodeCharP(";-----------------------------------------"));
3412 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3414 pic16_addpCode2pBlock(apb,
3415 pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3417 /* mark the end of this tiny function */
3418 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3423 abSym = Safe_calloc(1, sizeof(absSym));
3424 abSym->name = Safe_strdup( asymname );
3426 switch( _G.interruptvector ) {
3427 case 0: abSym->address = 0x000000; break;
3428 case 1: abSym->address = 0x000008; break;
3429 case 2: abSym->address = 0x000018; break;
3432 /* relocate interrupt vectors if needed */
3433 abSym->address += pic16_options.ivt_loc;
3435 addSet(&absSymSet, abSym);
3440 /* create the function header */
3441 pic16_emitcode(";","-----------------------------------------");
3442 pic16_emitcode(";"," function %s",sym->name);
3443 pic16_emitcode(";","-----------------------------------------");
3445 pic16_emitcode("","%s:",sym->rname);
3446 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3452 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3453 if(!strcmp(ab->name, sym->name)) {
3454 pic16_pBlockConvert2Absolute(pb);
3461 if(IFFUNC_ISNAKED(ftype)) {
3462 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3466 /* if critical function then turn interrupts off */
3467 if (IFFUNC_ISCRITICAL(ftype))
3468 pic16_emitcode("clr","ea");
3470 /* if this is an interrupt service routine then
3471 * save acc, b, dpl, dph */
3472 if (IFFUNC_ISISR(sym->type)) {
3475 _G.usefastretfie = 1; /* use shadow registers by default */
3476 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3477 if(!(_G.interruptvector == 1)) {
3479 /* do not save WREG,STATUS,BSR for high priority interrupts
3480 * because they are stored in the hardware shadow registers already */
3481 _G.usefastretfie = 0;
3482 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3483 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3484 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3488 /* these should really be optimized somehow, because not all
3489 * interrupt handlers modify them */
3490 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3491 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3492 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3493 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3495 // pic16_pBlockConvert2ISR(pb);
3497 /* if any registers used */
3498 if (sym->regsUsed) {
3499 /* save the registers used */
3500 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3501 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3502 if (bitVectBitValue(sym->regsUsed,i)) {
3504 fprintf(stderr, "%s:%d function %s uses register %s\n",
3505 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3506 pic16_regWithIdx(i)->name);
3509 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3512 if(!pic16_regWithIdx(i)->wasUsed) {
3513 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3514 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3516 pic16_regWithIdx(i)->wasUsed = 1;
3522 /* emit code to setup stack frame if user enabled,
3523 * and function is not main() */
3525 // fprintf(stderr, "function name: %s\n", sym->name);
3526 if(strcmp(sym->name, "main")) {
3527 if(/*!options.ommitFramePtr || */sym->regsUsed) {
3528 /* setup the stack frame */
3529 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3530 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3531 if(STACK_MODEL_LARGE)
3532 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3536 /* if callee-save to be used for this function
3537 * then save the registers being used in this function */
3538 // if (IFFUNC_CALLEESAVES(sym->type))
3542 // fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3544 // pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3546 /* if any registers used */
3547 if (sym->regsUsed) {
3548 /* save the registers used */
3549 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3550 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3551 if (bitVectBitValue(sym->regsUsed,i)) {
3554 fprintf(stderr, "%s:%d function %s uses register %s (wasUsed: %d, %p)\n",
3555 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3556 pic16_regWithIdx(i)->name,
3557 pic16_regWithIdx(i)->wasUsed,
3558 pic16_regWithIdx(i));
3561 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3563 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3564 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3565 // &pic16_pc_postdec1, 0));
3569 if(!pic16_regWithIdx(i)->wasUsed) {
3570 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3571 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3573 pic16_regWithIdx(i)->wasUsed = 1;
3585 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3587 if (options.useXstack) {
3588 pic16_emitcode("mov","r0,%s",spname);
3589 pic16_emitcode("mov","a,_bp");
3590 pic16_emitcode("movx","@r0,a");
3591 pic16_emitcode("inc","%s",spname);
3593 /* set up the stack */
3594 pic16_emitcode ("push","_bp"); /* save the callers stack */
3596 pic16_emitcode ("mov","_bp,%s",spname);
3599 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3601 /* adjust the stack for the function */
3606 werror(W_STACK_OVERFLOW,sym->name);
3608 if (i > 3 && sym->recvSize < 4) {
3609 pic16_emitcode ("mov","a,sp");
3610 pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3611 pic16_emitcode ("mov","sp,a");
3614 pic16_emitcode("inc","sp");
3618 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3620 pic16_emitcode ("mov","a,_spx");
3621 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3622 pic16_emitcode ("mov","_spx,a");
3627 /*-----------------------------------------------------------------*/
3628 /* genEndFunction - generates epilogue for functions */
3629 /*-----------------------------------------------------------------*/
3630 static void genEndFunction (iCode *ic)
3632 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3634 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3636 if(IFFUNC_ISNAKED(sym->type)) {
3637 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3641 /* add code for ISCRITICAL */
3644 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3646 pic16_emitcode ("mov","%s,_bp",spname);
3650 /* if use external stack but some variables were
3651 added to the local stack then decrement the
3653 if (options.useXstack && sym->stack) {
3654 pic16_emitcode("mov","a,sp");
3655 pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3656 pic16_emitcode("mov","sp,a");
3661 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3662 if (options.useXstack) {
3663 pic16_emitcode("mov","r0,%s",spname);
3664 pic16_emitcode("movx","a,@r0");
3665 pic16_emitcode("mov","_bp,a");
3666 pic16_emitcode("dec","%s",spname);
3670 pic16_emitcode ("pop","_bp");
3675 if (IFFUNC_ISISR(sym->type)) {
3676 /* now we need to restore the registers */
3677 /* if any registers used */
3678 if (sym->regsUsed) {
3681 /* restore registers used */
3682 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3683 for ( i = sym->regsUsed->size; i >= 0; i--) {
3684 if (bitVectBitValue(sym->regsUsed,i)) {
3686 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3687 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3688 // pic16_regWithIdx(i)->name);
3690 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3692 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3693 // &pic16_pc_preinc1,
3694 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3700 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3701 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3702 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3703 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3705 if(!(_G.interruptvector == 1)) {
3706 /* do not restore interrupt vector for WREG,STATUS,BSR
3707 * for high priority interrupt, see genFunction */
3709 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3710 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3711 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3714 _G.interruptvector = 0; /* sanity check */
3716 // pic16_pBlockConvert2ISR(pb);
3719 /* if debug then send end of function */
3720 /* if (options.debug && currFunc) */
3722 debugFile->writeEndFunction (currFunc, ic, 1);
3725 if(_G.usefastretfie)
3726 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3728 pic16_emitpcodeNULLop(POC_RETFIE);
3729 _G.usefastretfie = 0;
3731 if (IFFUNC_ISCRITICAL(sym->type))
3732 pic16_emitcode("setb","ea");
3735 // pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3737 /* if any registers used */
3738 if (sym->regsUsed) {
3740 /* save the registers used */
3741 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3742 for ( i = sym->regsUsed->size; i >= 0; i--) {
3743 if (bitVectBitValue(sym->regsUsed,i)) {
3745 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3746 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3747 // pic16_regWithIdx(i)->name);
3749 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3751 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3752 // &pic16_pc_preinc1,
3753 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3760 // pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3761 /* if debug then send end of function */
3763 debugFile->writeEndFunction (currFunc, ic, 1);
3766 /* insert code to restore stack frame, if user enabled it
3767 * and function is not main() */
3770 if(strcmp(sym->name, "main")) {
3771 if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3772 /* restore stack frame */
3773 if(STACK_MODEL_LARGE)
3774 pic16_emitpcode(POC_MOVFF,
3775 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3776 pic16_emitpcode(POC_MOVFF,
3777 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3781 pic16_emitpcodeNULLop(POC_RETURN);
3783 /* Mark the end of a function */
3784 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3790 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3794 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3796 if(dest->type != PO_WREG)
3797 pic16_emitpcode(POC_MOVWF, dest);
3799 if(dest->type == PO_WREG && (offset == 0)) {
3800 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3804 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3805 pic16_popGet(AOP(op), offset), dest));
3809 /*-----------------------------------------------------------------*/
3810 /* genRet - generate code for return statement */
3811 /*-----------------------------------------------------------------*/
3812 static void genRet (iCode *ic)
3817 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3818 /* if we have no return value then
3819 * just generate the "ret" */
3824 /* we have something to return then
3825 * move the return value into place */
3826 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3827 size = AOP_SIZE(IC_LEFT(ic));
3831 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3832 // pic16_emitpcode(POC_MOVFF,
3833 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3836 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3837 // pic16_emitpcode(POC_MOVFF,
3838 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3841 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3842 // pic16_emitpcode(POC_MOVFF,
3843 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3846 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3848 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3849 // pic16_emitpcode(POC_MOVFF,
3850 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3853 /* >32-bits, setup stack and FSR0 */
3855 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3856 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3858 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3860 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3865 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3866 pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3868 if(STACK_MODEL_LARGE) {
3869 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3870 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3872 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3877 /* old code, left here for reference -- VR */
3881 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3883 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3884 pic16_emitpcomment("push %s",l);
3887 DEBUGpic16_emitcode(";", "%d", __LINE__);
3888 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3889 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3891 if (strcmp(fReturn[offset],l)) {
3892 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3893 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3894 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3896 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3900 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3910 if (strcmp(fReturn[pushed],"a"))
3911 pic16_emitcode("pop",fReturn[pushed]);
3913 pic16_emitcode("pop","acc");
3919 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3922 /* generate a jump to the return label
3923 * if the next is not the return statement */
3924 if (!(ic->next && ic->next->op == LABEL
3925 && IC_LABEL(ic->next) == returnLabel)) {
3927 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3928 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3932 /*-----------------------------------------------------------------*/
3933 /* genLabel - generates a label */
3934 /*-----------------------------------------------------------------*/
3935 static void genLabel (iCode *ic)
3939 /* special case never generate */
3940 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3941 if (IC_LABEL(ic) == entryLabel)
3944 pic16_emitpLabel(IC_LABEL(ic)->key);
3945 pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3948 /*-----------------------------------------------------------------*/
3949 /* genGoto - generates a goto */
3950 /*-----------------------------------------------------------------*/
3952 static void genGoto (iCode *ic)
3954 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3955 pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3959 /*-----------------------------------------------------------------*/
3960 /* genMultbits :- multiplication of bits */
3961 /*-----------------------------------------------------------------*/
3962 static void genMultbits (operand *left,
3966 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3968 if(!pic16_sameRegs(AOP(result),AOP(right)))
3969 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3971 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3972 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3973 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3978 /*-----------------------------------------------------------------*/
3979 /* genMultOneByte : 8 bit multiplication & division */
3980 /*-----------------------------------------------------------------*/
3981 static void genMultOneByte (operand *left,
3986 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3987 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3988 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3990 /* (if two literals, the value is computed before) */
3991 /* if one literal, literal on the right */
3992 if (AOP_TYPE(left) == AOP_LIT){
3998 /* size is already checked in genMult == 1 */
3999 // size = AOP_SIZE(result);
4001 if (AOP_TYPE(right) == AOP_LIT){
4002 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4003 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4004 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4005 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4007 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4008 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4009 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4010 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4013 pic16_genMult8X8_8 (left, right,result);
4016 /*-----------------------------------------------------------------*/
4017 /* genMultOneWord : 16 bit multiplication */
4018 /*-----------------------------------------------------------------*/
4019 static void genMultOneWord (operand *left,
4024 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4025 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4026 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4028 /* (if two literals, the value is computed before)
4029 * if one literal, literal on the right */
4030 if (AOP_TYPE(left) == AOP_LIT){
4036 /* size is checked already == 2 */
4037 // size = AOP_SIZE(result);
4039 if (AOP_TYPE(right) == AOP_LIT) {
4040 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4041 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4042 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4043 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4045 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4046 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4047 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4048 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4051 pic16_genMult16X16_16(left, right,result);
4054 /*-----------------------------------------------------------------*/
4055 /* genMultOneLong : 32 bit multiplication */
4056 /*-----------------------------------------------------------------*/
4057 static void genMultOneLong (operand *left,
4062 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4063 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4064 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4066 /* (if two literals, the value is computed before)
4067 * if one literal, literal on the right */
4068 if (AOP_TYPE(left) == AOP_LIT){
4074 /* size is checked already == 4 */
4075 // size = AOP_SIZE(result);
4077 if (AOP_TYPE(right) == AOP_LIT) {
4078 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4079 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4080 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4081 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4083 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4084 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4085 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4086 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4089 pic16_genMult32X32_32(left, right,result);
4094 /*-----------------------------------------------------------------*/
4095 /* genMult - generates code for multiplication */
4096 /*-----------------------------------------------------------------*/
4097 static void genMult (iCode *ic)
4099 operand *left = IC_LEFT(ic);
4100 operand *right = IC_RIGHT(ic);
4101 operand *result= IC_RESULT(ic);
4103 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4104 /* assign the amsops */
4105 pic16_aopOp (left,ic,FALSE);
4106 pic16_aopOp (right,ic,FALSE);
4107 pic16_aopOp (result,ic,TRUE);
4109 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4111 /* special cases first *
4113 if (AOP_TYPE(left) == AOP_CRY
4114 && AOP_TYPE(right)== AOP_CRY) {
4115 genMultbits(left,right,result);
4119 /* if both are of size == 1 */
4120 if(AOP_SIZE(left) == 1
4121 && AOP_SIZE(right) == 1) {
4122 genMultOneByte(left,right,result);
4126 /* if both are of size == 2 */
4127 if(AOP_SIZE(left) == 2
4128 && AOP_SIZE(right) == 2) {
4129 genMultOneWord(left, right, result);
4133 /* if both are of size == 4 */
4134 if(AOP_SIZE(left) == 4
4135 && AOP_SIZE(right) == 4) {
4136 genMultOneLong(left, right, result);
4140 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4143 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4144 /* should have been converted to function call */
4148 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4149 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4150 pic16_freeAsmop(result,NULL,ic,TRUE);
4153 /*-----------------------------------------------------------------*/
4154 /* genDivbits :- division of bits */
4155 /*-----------------------------------------------------------------*/
4156 static void genDivbits (operand *left,
4163 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4164 /* the result must be bit */
4165 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4166 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4170 pic16_emitcode("div","ab");
4171 pic16_emitcode("rrc","a");
4172 pic16_aopPut(AOP(result),"c",0);
4175 /*-----------------------------------------------------------------*/
4176 /* genDivOneByte : 8 bit division */
4177 /*-----------------------------------------------------------------*/
4178 static void genDivOneByte (operand *left,
4182 sym_link *opetype = operandType(result);
4187 /* result = divident / divisor
4188 * - divident may be a register or a literal,
4189 * - divisor may be a register or a literal,
4190 * so there are 3 cases (literal / literal is optimized
4191 * by the front-end) to handle.
4192 * In addition we must handle signed and unsigned, which
4193 * result in 6 final different cases -- VR */
4195 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4196 size = AOP_SIZE(result) - 1;
4198 /* signed or unsigned */
4199 if (SPEC_USIGN(opetype)) {
4200 pCodeOp *pct1, /* count */
4203 symbol *label1, *label2, *label3;;
4206 /* unsigned is easy */
4208 pct1 = pic16_popGetTempReg();
4209 pct2 = pic16_popGetTempReg();
4210 pct3 = pic16_popGetTempReg();
4212 label1 = newiTempLabel(NULL);
4213 label2 = newiTempLabel(NULL);
4214 label3 = newiTempLabel(NULL);
4216 /* the following algorithm is extracted from divuint.c */
4218 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4219 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4221 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4223 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4225 pic16_emitpLabel(label1->key);
4228 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4232 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4236 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4238 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4239 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4241 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4242 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4243 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4245 pic16_emitpLabel( label3->key );
4246 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4247 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4251 pic16_emitpLabel(label2->key);
4252 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4253 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4254 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4256 /* result is in wreg */
4257 if(AOP_TYPE(result) != AOP_ACC)
4258 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4260 pic16_popReleaseTempReg( pct3 );
4261 pic16_popReleaseTempReg( pct2 );
4262 pic16_popReleaseTempReg( pct1 );
4267 /* signed is a little bit more difficult */
4269 /* save the signs of the operands */
4270 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4272 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4273 pic16_emitcode("push","acc"); /* save it on the stack */
4275 /* now sign adjust for both left & right */
4276 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4278 lbl = newiTempLabel(NULL);
4279 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4280 pic16_emitcode("cpl","a");
4281 pic16_emitcode("inc","a");
4282 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4283 pic16_emitcode("mov","b,a");
4285 /* sign adjust left side */
4286 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4289 lbl = newiTempLabel(NULL);
4290 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4291 pic16_emitcode("cpl","a");
4292 pic16_emitcode("inc","a");
4293 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4295 /* now the division */
4296 pic16_emitcode("div","ab");
4297 /* we are interested in the lower order
4299 pic16_emitcode("mov","b,a");
4300 lbl = newiTempLabel(NULL);
4301 pic16_emitcode("pop","acc");
4302 /* if there was an over flow we don't
4303 adjust the sign of the result */
4304 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4305 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4307 pic16_emitcode("clr","a");
4308 pic16_emitcode("subb","a,b");
4309 pic16_emitcode("mov","b,a");
4310 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4312 /* now we are done */
4313 pic16_aopPut(AOP(result),"b",0);
4315 pic16_emitcode("mov","c,b.7");
4316 pic16_emitcode("subb","a,acc");
4319 pic16_aopPut(AOP(result),"a",offset++);
4323 /*-----------------------------------------------------------------*/
4324 /* genDiv - generates code for division */
4325 /*-----------------------------------------------------------------*/
4326 static void genDiv (iCode *ic)
4328 operand *left = IC_LEFT(ic);
4329 operand *right = IC_RIGHT(ic);
4330 operand *result= IC_RESULT(ic);
4333 /* Division is a very lengthy algorithm, so it is better
4334 * to call support routines than inlining algorithm.
4335 * Division functions written here just in case someone
4336 * wants to inline and not use the support libraries -- VR */
4338 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4339 /* assign the amsops */
4340 pic16_aopOp (left,ic,FALSE);
4341 pic16_aopOp (right,ic,FALSE);
4342 pic16_aopOp (result,ic,TRUE);
4344 /* special cases first */
4346 if (AOP_TYPE(left) == AOP_CRY &&
4347 AOP_TYPE(right)== AOP_CRY) {
4348 genDivbits(left,right,result);
4352 /* if both are of size == 1 */
4353 if (AOP_SIZE(left) == 1 &&
4354 AOP_SIZE(right) == 1 ) {
4355 genDivOneByte(left,right,result);
4359 /* should have been converted to function call */
4362 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4363 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4364 pic16_freeAsmop(result,NULL,ic,TRUE);
4367 /*-----------------------------------------------------------------*/
4368 /* genModbits :- modulus of bits */
4369 /*-----------------------------------------------------------------*/
4370 static void genModbits (operand *left,
4377 /* the result must be bit */
4378 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4379 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4383 pic16_emitcode("div","ab");
4384 pic16_emitcode("mov","a,b");
4385 pic16_emitcode("rrc","a");
4386 pic16_aopPut(AOP(result),"c",0);
4389 /*-----------------------------------------------------------------*/
4390 /* genModOneByte : 8 bit modulus */
4391 /*-----------------------------------------------------------------*/
4392 static void genModOneByte (operand *left,
4396 sym_link *opetype = operandType(result);
4400 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4401 /* signed or unsigned */
4402 if (SPEC_USIGN(opetype)) {
4403 /* unsigned is easy */
4404 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4405 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4407 pic16_emitcode("div","ab");
4408 pic16_aopPut(AOP(result),"b",0);
4412 /* signed is a little bit more difficult */
4414 /* save the signs of the operands */
4415 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4418 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4419 pic16_emitcode("push","acc"); /* save it on the stack */
4421 /* now sign adjust for both left & right */
4422 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4425 lbl = newiTempLabel(NULL);
4426 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4427 pic16_emitcode("cpl","a");
4428 pic16_emitcode("inc","a");
4429 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4430 pic16_emitcode("mov","b,a");
4432 /* sign adjust left side */
4433 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4436 lbl = newiTempLabel(NULL);
4437 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4438 pic16_emitcode("cpl","a");
4439 pic16_emitcode("inc","a");
4440 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4442 /* now the multiplication */
4443 pic16_emitcode("div","ab");
4444 /* we are interested in the lower order
4446 lbl = newiTempLabel(NULL);
4447 pic16_emitcode("pop","acc");
4448 /* if there was an over flow we don't
4449 adjust the sign of the result */
4450 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4451 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4453 pic16_emitcode("clr","a");
4454 pic16_emitcode("subb","a,b");
4455 pic16_emitcode("mov","b,a");
4456 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4458 /* now we are done */
4459 pic16_aopPut(AOP(result),"b",0);
4463 /*-----------------------------------------------------------------*/
4464 /* genMod - generates code for division */
4465 /*-----------------------------------------------------------------*/
4466 static void genMod (iCode *ic)
4468 operand *left = IC_LEFT(ic);
4469 operand *right = IC_RIGHT(ic);
4470 operand *result= IC_RESULT(ic);
4472 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4473 /* assign the amsops */
4474 pic16_aopOp (left,ic,FALSE);
4475 pic16_aopOp (right,ic,FALSE);
4476 pic16_aopOp (result,ic,TRUE);
4478 /* special cases first */
4480 if (AOP_TYPE(left) == AOP_CRY &&
4481 AOP_TYPE(right)== AOP_CRY) {
4482 genModbits(left,right,result);
4486 /* if both are of size == 1 */
4487 if (AOP_SIZE(left) == 1 &&
4488 AOP_SIZE(right) == 1 ) {
4489 genModOneByte(left,right,result);
4493 /* should have been converted to function call */
4497 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4498 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4499 pic16_freeAsmop(result,NULL,ic,TRUE);
4502 /*-----------------------------------------------------------------*/
4503 /* genIfxJump :- will create a jump depending on the ifx */
4504 /*-----------------------------------------------------------------*/
4506 note: May need to add parameter to indicate when a variable is in bit space.
4508 static void genIfxJump (iCode *ic, char *jval)
4511 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4512 /* if true label then we jump if condition
4514 if ( IC_TRUE(ic) ) {
4516 if(strcmp(jval,"a") == 0)
4518 else if (strcmp(jval,"c") == 0)
4521 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4522 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4525 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4526 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4530 /* false label is present */
4531 if(strcmp(jval,"a") == 0)
4533 else if (strcmp(jval,"c") == 0)
4536 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4537 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4540 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4541 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4546 /* mark the icode as generated */
4553 /*-----------------------------------------------------------------*/
4555 /*-----------------------------------------------------------------*/
4556 static void genSkip(iCode *ifx,int status_bit)
4558 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4562 if ( IC_TRUE(ifx) ) {
4563 switch(status_bit) {
4578 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4579 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4583 switch(status_bit) {
4597 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4598 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4605 /*-----------------------------------------------------------------*/
4607 /*-----------------------------------------------------------------*/
4608 static void genSkipc(resolvedIfx *rifx)
4610 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4620 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4621 rifx->generated = 1;
4624 /*-----------------------------------------------------------------*/
4626 /*-----------------------------------------------------------------*/
4627 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4629 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4634 if( (rifx->condition ^ invert_condition) & 1)
4639 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4640 rifx->generated = 1;
4644 /*-----------------------------------------------------------------*/
4646 /*-----------------------------------------------------------------*/
4647 static void genSkipz(iCode *ifx, int condition)
4658 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4660 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4663 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4665 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4670 /*-----------------------------------------------------------------*/
4672 /*-----------------------------------------------------------------*/
4673 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4679 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4681 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4684 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4685 rifx->generated = 1;
4689 /*-----------------------------------------------------------------*/
4690 /* genChkZeroes :- greater or less than comparison */
4691 /* For each byte in a literal that is zero, inclusive or the */
4692 /* the corresponding byte in the operand with W */
4693 /* returns true if any of the bytes are zero */
4694 /*-----------------------------------------------------------------*/
4695 static int genChkZeroes(operand *op, int lit, int size)
4702 i = (lit >> (size*8)) & 0xff;
4706 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4708 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4717 /*-----------------------------------------------------------------*/
4718 /* genCmp :- greater or less than comparison */
4719 /*-----------------------------------------------------------------*/
4720 static void genCmp (operand *left,operand *right,
4721 operand *result, iCode *ifx, int sign)
4723 int size; //, offset = 0 ;
4724 unsigned long lit = 0L,i = 0;
4725 resolvedIfx rFalseIfx;
4726 // resolvedIfx rTrueIfx;
4728 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4731 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4732 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4736 resolveIfx(&rFalseIfx,ifx);
4737 truelbl = newiTempLabel(NULL);
4738 size = max(AOP_SIZE(left),AOP_SIZE(right));
4740 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4744 /* if literal is on the right then swap with left */
4745 if ((AOP_TYPE(right) == AOP_LIT)) {
4746 operand *tmp = right ;
4747 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4748 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4751 lit = (lit - 1) & mask;
4754 rFalseIfx.condition ^= 1;
4757 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4758 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4762 //if(IC_TRUE(ifx) == NULL)
4763 /* if left & right are bit variables */
4764 if (AOP_TYPE(left) == AOP_CRY &&
4765 AOP_TYPE(right) == AOP_CRY ) {
4766 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4767 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4769 /* subtract right from left if at the
4770 end the carry flag is set then we know that
4771 left is greater than right */
4773 symbol *lbl = newiTempLabel(NULL);
4776 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4777 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4781 if(AOP_TYPE(right) == AOP_LIT) {
4783 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4785 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4792 genSkipCond(&rFalseIfx,left,size-1,7);
4794 /* no need to compare to 0...*/
4795 /* NOTE: this is a de-generate compare that most certainly
4796 * creates some dead code. */
4797 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4799 if(ifx) ifx->generated = 1;
4806 //i = (lit >> (size*8)) & 0xff;
4807 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4809 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4811 i = ((0-lit) & 0xff);
4814 /* lit is 0x7f, all signed chars are less than
4815 * this except for 0x7f itself */
4816 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4817 genSkipz2(&rFalseIfx,0);
4819 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4820 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4821 genSkipc(&rFalseIfx);
4826 genSkipz2(&rFalseIfx,1);
4828 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4829 genSkipc(&rFalseIfx);
4833 if(ifx) ifx->generated = 1;
4837 /* chars are out of the way. now do ints and longs */
4840 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4847 genSkipCond(&rFalseIfx,left,size,7);
4848 if(ifx) ifx->generated = 1;
4853 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4855 //rFalseIfx.condition ^= 1;
4856 //genSkipCond(&rFalseIfx,left,size,7);
4857 //rFalseIfx.condition ^= 1;
4859 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4860 if(rFalseIfx.condition)
4861 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4863 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4865 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4866 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4867 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4870 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4872 if(rFalseIfx.condition) {
4874 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4880 genSkipc(&rFalseIfx);
4881 pic16_emitpLabel(truelbl->key);
4882 if(ifx) ifx->generated = 1;
4889 if( (lit & 0xff) == 0) {
4890 /* lower byte is zero */
4891 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4892 i = ((lit >> 8) & 0xff) ^0x80;
4893 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4894 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4895 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4896 genSkipc(&rFalseIfx);
4899 if(ifx) ifx->generated = 1;
4904 /* Special cases for signed longs */
4905 if( (lit & 0xffffff) == 0) {
4906 /* lower byte is zero */
4907 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4908 i = ((lit >> 8*3) & 0xff) ^0x80;
4909 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4910 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4911 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4912 genSkipc(&rFalseIfx);
4915 if(ifx) ifx->generated = 1;
4923 if(lit & (0x80 << (size*8))) {
4924 /* lit is negative */
4925 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4927 //genSkipCond(&rFalseIfx,left,size,7);
4929 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4931 if(rFalseIfx.condition)
4932 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4934 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4938 /* lit is positive */
4939 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4940 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4941 if(rFalseIfx.condition)
4942 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4944 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4949 This works, but is only good for ints.
4950 It also requires a "known zero" register.
4951 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4952 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4953 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
4954 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4955 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4956 genSkipc(&rFalseIfx);
4958 pic16_emitpLabel(truelbl->key);
4959 if(ifx) ifx->generated = 1;
4963 /* There are no more special cases, so perform a general compare */
4965 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4966 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4970 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4972 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4974 //rFalseIfx.condition ^= 1;
4975 genSkipc(&rFalseIfx);
4977 pic16_emitpLabel(truelbl->key);
4979 if(ifx) ifx->generated = 1;
4986 /* sign is out of the way. So now do an unsigned compare */
4987 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4990 /* General case - compare to an unsigned literal on the right.*/
4992 i = (lit >> (size*8)) & 0xff;
4993 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4994 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4996 i = (lit >> (size*8)) & 0xff;
4999 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5001 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5003 /* this byte of the lit is zero,
5004 *if it's not the last then OR in the variable */
5006 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5011 pic16_emitpLabel(lbl->key);
5012 // pic16_emitpLabel(truelbl->key);
5013 //if(emitFinalCheck)
5014 genSkipc(&rFalseIfx);
5016 pic16_emitpLabel(truelbl->key);
5018 if(ifx) ifx->generated = 1;
5025 if(AOP_TYPE(left) == AOP_LIT) {
5026 //symbol *lbl = newiTempLabel(NULL);
5028 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5031 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5034 if((lit == 0) && (sign == 0)){
5037 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5039 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5041 genSkipz2(&rFalseIfx,0);
5042 if(ifx) ifx->generated = 1;
5049 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5050 /* degenerate compare can never be true */
5051 if(rFalseIfx.condition == 0)
5052 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5054 if(ifx) ifx->generated = 1;
5059 /* signed comparisons to a literal byte */
5061 int lp1 = (lit+1) & 0xff;
5063 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5066 rFalseIfx.condition ^= 1;
5067 genSkipCond(&rFalseIfx,right,0,7);
5070 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5071 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5072 genSkipz2(&rFalseIfx,1);
5075 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5076 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5077 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5078 rFalseIfx.condition ^= 1;
5079 genSkipc(&rFalseIfx);
5083 /* unsigned comparisons to a literal byte */
5085 switch(lit & 0xff ) {
5087 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5088 genSkipz2(&rFalseIfx,0);
5091 rFalseIfx.condition ^= 1;
5092 genSkipCond(&rFalseIfx,right,0,7);
5096 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5097 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5098 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5099 rFalseIfx.condition ^= 1;
5100 if (AOP_TYPE(result) == AOP_CRY)
5101 genSkipc(&rFalseIfx);
5103 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5104 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5110 if(ifx) ifx->generated = 1;
5111 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5117 /* Size is greater than 1 */
5125 /* this means lit = 0xffffffff, or -1 */
5128 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5129 rFalseIfx.condition ^= 1;
5130 genSkipCond(&rFalseIfx,right,size,7);
5131 if(ifx) ifx->generated = 1;
5138 if(rFalseIfx.condition) {
5139 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5140 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5143 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5145 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5149 if(rFalseIfx.condition) {
5150 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5151 pic16_emitpLabel(truelbl->key);
5153 rFalseIfx.condition ^= 1;
5154 genSkipCond(&rFalseIfx,right,s,7);
5157 if(ifx) ifx->generated = 1;
5161 if((size == 1) && (0 == (lp1&0xff))) {
5162 /* lower byte of signed word is zero */
5163 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5164 i = ((lp1 >> 8) & 0xff) ^0x80;
5165 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5166 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5167 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5168 rFalseIfx.condition ^= 1;
5169 genSkipc(&rFalseIfx);
5172 if(ifx) ifx->generated = 1;
5176 if(lit & (0x80 << (size*8))) {
5177 /* Lit is less than zero */
5178 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5179 //rFalseIfx.condition ^= 1;
5180 //genSkipCond(&rFalseIfx,left,size,7);
5181 //rFalseIfx.condition ^= 1;
5182 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5183 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5185 if(rFalseIfx.condition)
5186 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5188 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5192 /* Lit is greater than or equal to zero */
5193 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5194 //rFalseIfx.condition ^= 1;
5195 //genSkipCond(&rFalseIfx,right,size,7);
5196 //rFalseIfx.condition ^= 1;
5198 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5199 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5201 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5202 if(rFalseIfx.condition)
5203 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5205 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5210 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5211 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5215 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5217 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5219 rFalseIfx.condition ^= 1;
5220 //rFalseIfx.condition = 1;
5221 genSkipc(&rFalseIfx);
5223 pic16_emitpLabel(truelbl->key);
5225 if(ifx) ifx->generated = 1;
5230 /* compare word or long to an unsigned literal on the right.*/
5235 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5238 break; /* handled above */
5241 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5243 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5244 genSkipz2(&rFalseIfx,0);
5248 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5250 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5253 if(rFalseIfx.condition)
5254 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5256 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5259 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5260 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5262 rFalseIfx.condition ^= 1;
5263 genSkipc(&rFalseIfx);
5266 pic16_emitpLabel(truelbl->key);
5268 if(ifx) ifx->generated = 1;
5274 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5275 i = (lit >> (size*8)) & 0xff;
5277 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5278 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5281 i = (lit >> (size*8)) & 0xff;
5284 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5286 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5288 /* this byte of the lit is zero,
5289 * if it's not the last then OR in the variable */
5291 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5296 pic16_emitpLabel(lbl->key);
5298 rFalseIfx.condition ^= 1;
5300 genSkipc(&rFalseIfx);
5304 pic16_emitpLabel(truelbl->key);
5305 if(ifx) ifx->generated = 1;
5309 /* Compare two variables */
5311 DEBUGpic16_emitcode(";sign","%d",sign);
5315 /* Sigh. thus sucks... */
5319 pctemp = pic16_popGetTempReg();
5320 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5321 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5322 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5323 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5324 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5325 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5326 pic16_popReleaseTempReg(pctemp);
5328 /* Signed char comparison */
5329 /* Special thanks to Nikolai Golovchenko for this snippet */
5330 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5331 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5332 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5333 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5334 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5335 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5337 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5338 genSkipc(&rFalseIfx);
5340 if(ifx) ifx->generated = 1;
5346 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5347 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5351 /* The rest of the bytes of a multi-byte compare */
5355 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5358 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5359 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5364 pic16_emitpLabel(lbl->key);
5366 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5367 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5368 (AOP_TYPE(result) == AOP_REG)) {
5369 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5370 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5372 genSkipc(&rFalseIfx);
5374 //genSkipc(&rFalseIfx);
5375 if(ifx) ifx->generated = 1;
5382 if ((AOP_TYPE(result) != AOP_CRY)
5383 && AOP_SIZE(result)) {
5384 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5386 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5388 pic16_outBitC(result);
5390 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5391 /* if the result is used in the next
5392 ifx conditional branch then generate
5393 code a little differently */
5395 genIfxJump (ifx,"c");
5397 pic16_outBitC(result);
5398 /* leave the result in acc */
5403 /*-----------------------------------------------------------------*/
5404 /* genCmpGt :- greater than comparison */
5405 /*-----------------------------------------------------------------*/
5406 static void genCmpGt (iCode *ic, iCode *ifx)
5408 operand *left, *right, *result;
5409 sym_link *letype , *retype;
5412 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5414 right= IC_RIGHT(ic);
5415 result = IC_RESULT(ic);
5417 letype = getSpec(operandType(left));
5418 retype =getSpec(operandType(right));
5419 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5420 /* assign the amsops */
5421 pic16_aopOp (left,ic,FALSE);
5422 pic16_aopOp (right,ic,FALSE);
5423 pic16_aopOp (result,ic,TRUE);
5425 genCmp(right, left, result, ifx, sign);
5427 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5428 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5429 pic16_freeAsmop(result,NULL,ic,TRUE);
5432 /*-----------------------------------------------------------------*/
5433 /* genCmpLt - less than comparisons */
5434 /*-----------------------------------------------------------------*/
5435 static void genCmpLt (iCode *ic, iCode *ifx)
5437 operand *left, *right, *result;
5438 sym_link *letype , *retype;
5441 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5443 right= IC_RIGHT(ic);
5444 result = IC_RESULT(ic);
5446 letype = getSpec(operandType(left));
5447 retype =getSpec(operandType(right));
5448 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5450 /* assign the amsops */
5451 pic16_aopOp (left,ic,FALSE);
5452 pic16_aopOp (right,ic,FALSE);
5453 pic16_aopOp (result,ic,TRUE);
5455 genCmp(left, right, result, ifx, sign);
5457 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5458 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5459 pic16_freeAsmop(result,NULL,ic,TRUE);
5464 // FIXME reenable literal optimisation when the pic16 port is stable
5466 /*-----------------------------------------------------------------*/
5467 /* genc16bit2lit - compare a 16 bit value to a literal */
5468 /*-----------------------------------------------------------------*/
5469 static void genc16bit2lit(operand *op, int lit, int offset)
5473 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
5474 if( (lit&0xff) == 0)
5479 switch( BYTEofLONG(lit,i)) {
5481 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5484 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5487 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5490 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5491 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5496 switch( BYTEofLONG(lit,i)) {
5498 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5502 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5506 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5509 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5511 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5520 /*-----------------------------------------------------------------*/
5521 /* gencjneshort - compare and jump if not equal */
5522 /*-----------------------------------------------------------------*/
5523 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5525 int size = max(AOP_SIZE(left),AOP_SIZE(right));
5527 int res_offset = 0; /* the result may be a different size then left or right */
5528 int res_size = AOP_SIZE(result);
5530 symbol *lbl, *lbl_done;
5532 unsigned long lit = 0L;
5533 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5536 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5538 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
5539 resolveIfx(&rIfx,ifx);
5540 lbl = newiTempLabel(NULL);
5541 lbl_done = newiTempLabel(NULL);
5544 /* if the left side is a literal or
5545 if the right is in a pointer register and left
5547 if ((AOP_TYPE(left) == AOP_LIT) ||
5548 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5553 if(AOP_TYPE(right) == AOP_LIT)
5554 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5556 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5557 preserve_result = 1;
5559 if(result && !preserve_result)
5562 for(i = 0; i < AOP_SIZE(result); i++)
5563 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5567 /* if the right side is a literal then anything goes */
5568 if (AOP_TYPE(right) == AOP_LIT &&
5569 AOP_TYPE(left) != AOP_DIR ) {
5572 genc16bit2lit(left, lit, 0);
5574 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5577 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5580 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5581 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5583 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5587 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5589 if(res_offset < res_size-1)
5597 /* if the right side is in a register or in direct space or
5598 if the left is a pointer register & right is not */
5599 else if (AOP_TYPE(right) == AOP_REG ||
5600 AOP_TYPE(right) == AOP_DIR ||
5601 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5602 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5603 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5604 int lbl_key = lbl->key;
5607 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5608 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5610 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5611 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5612 __FUNCTION__,__LINE__);
5616 /* switch(size) { */
5618 /* genc16bit2lit(left, lit, 0); */
5620 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5625 if((AOP_TYPE(left) == AOP_DIR) &&
5626 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5628 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5629 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5631 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5633 switch (lit & 0xff) {
5635 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5638 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5639 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5640 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5644 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5645 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5646 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5647 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5651 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5652 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5657 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5660 if(AOP_TYPE(result) == AOP_CRY) {
5661 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5666 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5668 /* fix me. probably need to check result size too */
5669 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5674 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5675 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5682 if(res_offset < res_size-1)
5687 } else if(AOP_TYPE(right) == AOP_REG &&
5688 AOP_TYPE(left) != AOP_DIR){
5691 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5692 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5693 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5698 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5700 if(res_offset < res_size-1)
5705 /* right is a pointer reg need both a & b */
5707 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5709 pic16_emitcode("mov","b,%s",l);
5710 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5711 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5716 if(result && preserve_result)
5719 for(i = 0; i < AOP_SIZE(result); i++)
5720 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5723 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5725 if(result && preserve_result)
5726 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5729 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5731 pic16_emitpLabel(lbl->key);
5733 if(result && preserve_result)
5736 for(i = 0; i < AOP_SIZE(result); i++)
5737 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5739 pic16_emitpLabel(lbl_done->key);
5742 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5750 /*-----------------------------------------------------------------*/
5751 /* gencjne - compare and jump if not equal */
5752 /*-----------------------------------------------------------------*/
5753 static void gencjne(operand *left, operand *right, iCode *ifx)
5755 symbol *tlbl = newiTempLabel(NULL);
5757 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5758 gencjneshort(left, right, lbl);
5760 pic16_emitcode("mov","a,%s",one);
5761 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5762 pic16_emitcode("","%05d_DS_:",lbl->key+100);
5763 pic16_emitcode("clr","a");
5764 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5766 pic16_emitpLabel(lbl->key);
5767 pic16_emitpLabel(tlbl->key);
5773 /*-----------------------------------------------------------------*/
5774 /* is_LitOp - check if operand has to be treated as literal */
5775 /*-----------------------------------------------------------------*/
5776 static bool is_LitOp(operand *op)
5778 return (AOP_TYPE(op) == AOP_LIT)
5779 || ( (AOP_TYPE(op) == AOP_PCODE)
5780 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5781 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));
5784 /*-----------------------------------------------------------------*/
5785 /* is_LitAOp - check if operand has to be treated as literal */
5786 /*-----------------------------------------------------------------*/
5787 static bool is_LitAOp(asmop *aop)
5789 return (aop->type == AOP_LIT)
5790 || ( (aop->type == AOP_PCODE)
5791 && ( (aop->aopu.pcop->type == PO_LITERAL)
5792 || (aop->aopu.pcop->type == PO_IMMEDIATE) ));
5797 /*-----------------------------------------------------------------*/
5798 /* genCmpEq - generates code for equal to */
5799 /*-----------------------------------------------------------------*/
5800 static void genCmpEq (iCode *ic, iCode *ifx)
5802 operand *left, *right, *result;
5803 symbol *falselbl = newiTempLabel(NULL);
5804 symbol *donelbl = newiTempLabel(NULL);
5806 int preserve_result = 0;
5807 int generate_result = 0;
5810 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5811 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5812 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5814 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5815 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5817 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5819 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5820 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5824 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5826 operand *tmp = right ;
5831 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5832 preserve_result = 1;
5834 if(result && AOP_SIZE(result))
5835 generate_result = 1;
5837 if(generate_result && !preserve_result)
5839 for(i = 0; i < AOP_SIZE(result); i++)
5840 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5843 for(i=0; i < AOP_SIZE(left); i++)
5845 if(AOP_TYPE(left) != AOP_ACC)
5848 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5850 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5853 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
5855 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
5857 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5862 if(generate_result && preserve_result)
5864 for(i = 0; i < AOP_SIZE(result); i++)
5865 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5869 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5871 if(generate_result && preserve_result)
5872 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5874 if(ifx && IC_TRUE(ifx))
5875 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5877 if(ifx && IC_FALSE(ifx))
5878 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5880 pic16_emitpLabel(falselbl->key);
5884 if(ifx && IC_FALSE(ifx))
5885 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5887 if(generate_result && preserve_result)
5889 for(i = 0; i < AOP_SIZE(result); i++)
5890 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5893 pic16_emitpLabel(donelbl->key);
5899 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5900 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5901 pic16_freeAsmop(result,NULL,ic,TRUE);
5907 // old version kept for reference
5909 /*-----------------------------------------------------------------*/
5910 /* genCmpEq - generates code for equal to */
5911 /*-----------------------------------------------------------------*/
5912 static void genCmpEq (iCode *ic, iCode *ifx)
5914 operand *left, *right, *result;
5915 unsigned long lit = 0L;
5917 symbol *falselbl = newiTempLabel(NULL);
5920 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5923 DEBUGpic16_emitcode ("; ifx is non-null","");
5925 DEBUGpic16_emitcode ("; ifx is null","");
5927 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5928 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5929 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5931 size = max(AOP_SIZE(left),AOP_SIZE(right));
5933 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5935 /* if literal, literal on the right or
5936 if the right is in a pointer register and left
5938 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
5939 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5940 operand *tmp = right ;
5946 if(ifx && !AOP_SIZE(result)){
5948 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
5949 /* if they are both bit variables */
5950 if (AOP_TYPE(left) == AOP_CRY &&
5951 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5952 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
5953 if(AOP_TYPE(right) == AOP_LIT){
5954 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5956 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5957 pic16_emitcode("cpl","c");
5958 } else if(lit == 1L) {
5959 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5961 pic16_emitcode("clr","c");
5963 /* AOP_TYPE(right) == AOP_CRY */
5965 symbol *lbl = newiTempLabel(NULL);
5966 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5967 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5968 pic16_emitcode("cpl","c");
5969 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5971 /* if true label then we jump if condition
5973 tlbl = newiTempLabel(NULL);
5974 if ( IC_TRUE(ifx) ) {
5975 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5976 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5978 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5979 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5981 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5984 /* left and right are both bit variables, result is carry */
5987 resolveIfx(&rIfx,ifx);
5989 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5990 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5991 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5992 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5997 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
5999 /* They're not both bit variables. Is the right a literal? */
6000 if(AOP_TYPE(right) == AOP_LIT) {
6001 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6006 switch(lit & 0xff) {
6008 if ( IC_TRUE(ifx) ) {
6009 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6011 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6013 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6014 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6018 if ( IC_TRUE(ifx) ) {
6019 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6021 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6023 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6024 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6028 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6030 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6035 /* end of size == 1 */
6039 genc16bit2lit(left,lit,offset);
6042 /* end of size == 2 */
6047 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6048 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6049 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6050 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6053 /* search for patterns that can be optimized */
6055 genc16bit2lit(left,lit,0);
6059 emitSKPZ; // if hi word unequal
6061 emitSKPNZ; // if hi word equal
6063 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6064 genc16bit2lit(left,lit,2);
6067 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6068 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6072 pic16_emitpLabel(falselbl->key);
6081 } else if(AOP_TYPE(right) == AOP_CRY ) {
6082 /* we know the left is not a bit, but that the right is */
6083 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6084 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6085 pic16_popGet(AOP(right),offset));
6086 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6088 /* if the two are equal, then W will be 0 and the Z bit is set
6089 * we could test Z now, or go ahead and check the high order bytes if
6090 * the variable we're comparing is larger than a byte. */
6093 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6095 if ( IC_TRUE(ifx) ) {
6097 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6098 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6101 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6102 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6106 /* They're both variables that are larger than bits */
6109 tlbl = newiTempLabel(NULL);
6112 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6113 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6115 if ( IC_TRUE(ifx) ) {
6119 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6121 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6122 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6126 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6129 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6130 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6135 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6137 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6138 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6142 if(s>1 && IC_TRUE(ifx)) {
6143 pic16_emitpLabel(tlbl->key);
6144 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6148 /* mark the icode as generated */
6153 /* if they are both bit variables */
6154 if (AOP_TYPE(left) == AOP_CRY &&
6155 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6156 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
6157 if(AOP_TYPE(right) == AOP_LIT){
6158 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6160 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6161 pic16_emitcode("cpl","c");
6162 } else if(lit == 1L) {
6163 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6165 pic16_emitcode("clr","c");
6167 /* AOP_TYPE(right) == AOP_CRY */
6169 symbol *lbl = newiTempLabel(NULL);
6170 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6171 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6172 pic16_emitcode("cpl","c");
6173 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6176 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6177 pic16_outBitC(result);
6181 genIfxJump (ifx,"c");
6184 /* if the result is used in an arithmetic operation
6185 then put the result in place */
6186 pic16_outBitC(result);
6189 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
6190 gencjne(left,right,result,ifx);
6193 gencjne(left,right,newiTempLabel(NULL));
6195 if(IC_TRUE(ifx)->key)
6196 gencjne(left,right,IC_TRUE(ifx)->key);
6198 gencjne(left,right,IC_FALSE(ifx)->key);
6202 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6203 pic16_aopPut(AOP(result),"a",0);
6208 genIfxJump (ifx,"a");
6212 /* if the result is used in an arithmetic operation
6213 then put the result in place */
6215 if (AOP_TYPE(result) != AOP_CRY)
6216 pic16_outAcc(result);
6218 /* leave the result in acc */
6222 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6223 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6224 pic16_freeAsmop(result,NULL,ic,TRUE);
6228 /*-----------------------------------------------------------------*/
6229 /* ifxForOp - returns the icode containing the ifx for operand */
6230 /*-----------------------------------------------------------------*/
6231 static iCode *ifxForOp ( operand *op, iCode *ic )
6233 /* if true symbol then needs to be assigned */
6234 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6235 if (IS_TRUE_SYMOP(op))
6238 /* if this has register type condition and
6239 the next instruction is ifx with the same operand
6240 and live to of the operand is upto the ifx only then */
6242 && ic->next->op == IFX
6243 && IC_COND(ic->next)->key == op->key
6244 && OP_SYMBOL(op)->liveTo <= ic->next->seq
6246 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6251 ic->next->op == IFX &&
6252 IC_COND(ic->next)->key == op->key) {
6253 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6257 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6259 ic->next->op == IFX)
6260 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6263 ic->next->op == IFX &&
6264 IC_COND(ic->next)->key == op->key) {
6265 DEBUGpic16_emitcode ("; "," key is okay");
6266 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6267 OP_SYMBOL(op)->liveTo,
6272 /* the code below is completely untested
6273 * it just allows ulong2fs.c compile -- VR */
6276 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6277 __FILE__, __FUNCTION__, __LINE__);
6279 /* if this has register type condition and
6280 the next instruction is ifx with the same operand
6281 and live to of the operand is upto the ifx only then */
6283 ic->next->op == IFX &&
6284 IC_COND(ic->next)->key == op->key &&
6285 OP_SYMBOL(op)->liveTo <= ic->next->seq )
6289 ic->next->op == IFX &&
6290 IC_COND(ic->next)->key == op->key) {
6291 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6295 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6296 __FILE__, __FUNCTION__, __LINE__);
6298 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
6303 /*-----------------------------------------------------------------*/
6304 /* genAndOp - for && operation */
6305 /*-----------------------------------------------------------------*/
6306 static void genAndOp (iCode *ic)
6308 operand *left,*right, *result;
6311 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6312 /* note here that && operations that are in an
6313 if statement are taken away by backPatchLabels
6314 only those used in arthmetic operations remain */
6315 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6316 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6317 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6319 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6321 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6322 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6323 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6325 /* if both are bit variables */
6326 /* if (AOP_TYPE(left) == AOP_CRY && */
6327 /* AOP_TYPE(right) == AOP_CRY ) { */
6328 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6329 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6330 /* pic16_outBitC(result); */
6332 /* tlbl = newiTempLabel(NULL); */
6333 /* pic16_toBoolean(left); */
6334 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6335 /* pic16_toBoolean(right); */
6336 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6337 /* pic16_outBitAcc(result); */
6340 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6341 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6342 pic16_freeAsmop(result,NULL,ic,TRUE);
6346 /*-----------------------------------------------------------------*/
6347 /* genOrOp - for || operation */
6348 /*-----------------------------------------------------------------*/
6351 modified this code, but it doesn't appear to ever get called
6354 static void genOrOp (iCode *ic)
6356 operand *left,*right, *result;
6359 /* note here that || operations that are in an
6360 if statement are taken away by backPatchLabels
6361 only those used in arthmetic operations remain */
6362 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6363 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6364 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6365 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6367 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6369 /* if both are bit variables */
6370 if (AOP_TYPE(left) == AOP_CRY &&
6371 AOP_TYPE(right) == AOP_CRY ) {
6372 pic16_emitcode("clrc","");
6373 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6374 AOP(left)->aopu.aop_dir,
6375 AOP(left)->aopu.aop_dir);
6376 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6377 AOP(right)->aopu.aop_dir,
6378 AOP(right)->aopu.aop_dir);
6379 pic16_emitcode("setc","");
6382 tlbl = newiTempLabel(NULL);
6383 pic16_toBoolean(left);
6385 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6386 pic16_toBoolean(right);
6387 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6389 pic16_outBitAcc(result);
6392 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6393 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6394 pic16_freeAsmop(result,NULL,ic,TRUE);
6397 /*-----------------------------------------------------------------*/
6398 /* isLiteralBit - test if lit == 2^n */
6399 /*-----------------------------------------------------------------*/
6400 static int isLiteralBit(unsigned long lit)
6402 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6403 0x100L,0x200L,0x400L,0x800L,
6404 0x1000L,0x2000L,0x4000L,0x8000L,
6405 0x10000L,0x20000L,0x40000L,0x80000L,
6406 0x100000L,0x200000L,0x400000L,0x800000L,
6407 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6408 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6411 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6412 for(idx = 0; idx < 32; idx++)
6418 /*-----------------------------------------------------------------*/
6419 /* continueIfTrue - */
6420 /*-----------------------------------------------------------------*/
6421 static void continueIfTrue (iCode *ic)
6423 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6425 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6429 /*-----------------------------------------------------------------*/
6431 /*-----------------------------------------------------------------*/
6432 static void jumpIfTrue (iCode *ic)
6434 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6436 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6440 /*-----------------------------------------------------------------*/
6441 /* jmpTrueOrFalse - */
6442 /*-----------------------------------------------------------------*/
6443 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6445 // ugly but optimized by peephole
6446 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6448 symbol *nlbl = newiTempLabel(NULL);
6449 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
6450 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6451 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6452 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6455 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6456 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6461 /*-----------------------------------------------------------------*/
6462 /* genAnd - code for and */
6463 /*-----------------------------------------------------------------*/
6464 static void genAnd (iCode *ic, iCode *ifx)
6466 operand *left, *right, *result;
6468 unsigned long lit = 0L;
6473 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6474 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6475 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6476 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6478 resolveIfx(&rIfx,ifx);
6480 /* if left is a literal & right is not then exchange them */
6481 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6482 AOP_NEEDSACC(left)) {
6483 operand *tmp = right ;
6488 /* if result = right then exchange them */
6489 if(pic16_sameRegs(AOP(result),AOP(right))){
6490 operand *tmp = right ;
6495 /* if right is bit then exchange them */
6496 if (AOP_TYPE(right) == AOP_CRY &&
6497 AOP_TYPE(left) != AOP_CRY){
6498 operand *tmp = right ;
6502 if(AOP_TYPE(right) == AOP_LIT)
6503 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6505 size = AOP_SIZE(result);
6507 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6510 // result = bit & yy;
6511 if (AOP_TYPE(left) == AOP_CRY){
6512 // c = bit & literal;
6513 if(AOP_TYPE(right) == AOP_LIT){
6515 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6518 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6521 if(size && (AOP_TYPE(result) == AOP_CRY)){
6522 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6525 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6529 pic16_emitcode("clr","c");
6532 if (AOP_TYPE(right) == AOP_CRY){
6534 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6535 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6538 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6540 pic16_emitcode("rrc","a");
6541 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6547 pic16_outBitC(result);
6549 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6550 genIfxJump(ifx, "c");
6554 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6555 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6556 if((AOP_TYPE(right) == AOP_LIT) &&
6557 (AOP_TYPE(result) == AOP_CRY) &&
6558 (AOP_TYPE(left) != AOP_CRY)){
6559 int posbit = isLiteralBit(lit);
6563 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6566 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6572 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6573 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6575 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6576 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6579 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6580 size = AOP_SIZE(left);
6583 int bp = posbit, ofs=0;
6590 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6591 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
6595 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6596 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6598 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6605 symbol *tlbl = newiTempLabel(NULL);
6606 int sizel = AOP_SIZE(left);
6608 /* here to add patch from Aaron */
6610 emitSETC; //pic16_emitcode("setb","c");
6614 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6617 /* patch provided by Aaron Colwell */
6618 if((posbit = isLiteralBit(bytelit)) != 0) {
6619 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
6620 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),
6623 (posbit-1),0, PO_GPR_REGISTER));
6625 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
6627 if (bytelit == 0xff) {
6628 /* Aaron had a MOVF instruction here, changed to MOVFW cause
6629 * a peephole could optimize it out -- VR */
6630 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6632 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6633 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
6636 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
6637 pic16_popGetLabel(tlbl->key));
6641 /* old code, left here for reference -- VR 09/2004 */
6642 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6644 if((posbit = isLiteralBit(bytelit)) != 0)
6645 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6647 if(bytelit != 0x0FFL)
6648 pic16_emitcode("anl","a,%s",
6649 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6650 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6656 // bit = left & literal
6659 pic16_emitpLabel(tlbl->key);
6661 // if(left & literal)
6664 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
6665 pic16_emitpLabel(tlbl->key);
6672 pic16_outBitC(result);
6676 /* if left is same as result */
6677 if(pic16_sameRegs(AOP(result),AOP(left))){
6679 for(;size--; offset++,lit>>=8) {
6680 if(AOP_TYPE(right) == AOP_LIT){
6681 switch(lit & 0xff) {
6683 /* and'ing with 0 has clears the result */
6684 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6685 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6688 /* and'ing with 0xff is a nop when the result and left are the same */
6693 int p = my_powof2( (~lit) & 0xff );
6695 /* only one bit is set in the literal, so use a bcf instruction */
6696 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6697 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6700 pic16_emitcode("movlw","0x%x", (lit & 0xff));
6701 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6702 if(know_W != (lit&0xff))
6703 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6705 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6710 if (AOP_TYPE(left) == AOP_ACC) {
6711 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6713 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6714 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6721 // left & result in different registers
6722 if(AOP_TYPE(result) == AOP_CRY){
6724 // if(size), result in bit
6725 // if(!size && ifx), conditional oper: if(left & right)
6726 symbol *tlbl = newiTempLabel(NULL);
6727 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6729 pic16_emitcode("setb","c");
6731 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6732 pic16_emitcode("anl","a,%s",
6733 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6734 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6739 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6740 pic16_outBitC(result);
6742 jmpTrueOrFalse(ifx, tlbl);
6744 for(;(size--);offset++) {
6746 // result = left & right
6747 if(AOP_TYPE(right) == AOP_LIT){
6748 int t = (lit >> (offset*8)) & 0x0FFL;
6751 pic16_emitcode("clrf","%s",
6752 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6753 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6756 pic16_emitcode("movf","%s,w",
6757 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6758 pic16_emitcode("movwf","%s",
6759 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6760 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6761 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6764 pic16_emitcode("movlw","0x%x",t);
6765 pic16_emitcode("andwf","%s,w",
6766 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6767 pic16_emitcode("movwf","%s",
6768 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6770 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6771 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6772 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6777 if (AOP_TYPE(left) == AOP_ACC) {
6778 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6779 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6781 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6782 pic16_emitcode("andwf","%s,w",
6783 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6784 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6785 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6787 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6788 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6794 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6795 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6796 pic16_freeAsmop(result,NULL,ic,TRUE);
6799 /*-----------------------------------------------------------------*/
6800 /* genOr - code for or */
6801 /*-----------------------------------------------------------------*/
6802 static void genOr (iCode *ic, iCode *ifx)
6804 operand *left, *right, *result;
6806 unsigned long lit = 0L;
6808 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6810 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6811 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6812 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6814 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6816 /* if left is a literal & right is not then exchange them */
6817 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6818 AOP_NEEDSACC(left)) {
6819 operand *tmp = right ;
6824 /* if result = right then exchange them */
6825 if(pic16_sameRegs(AOP(result),AOP(right))){
6826 operand *tmp = right ;
6831 /* if right is bit then exchange them */
6832 if (AOP_TYPE(right) == AOP_CRY &&
6833 AOP_TYPE(left) != AOP_CRY){
6834 operand *tmp = right ;
6839 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6841 if(AOP_TYPE(right) == AOP_LIT)
6842 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6844 size = AOP_SIZE(result);
6848 if (AOP_TYPE(left) == AOP_CRY){
6849 if(AOP_TYPE(right) == AOP_LIT){
6850 // c = bit & literal;
6852 // lit != 0 => result = 1
6853 if(AOP_TYPE(result) == AOP_CRY){
6855 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6856 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6857 // AOP(result)->aopu.aop_dir,
6858 // AOP(result)->aopu.aop_dir);
6860 continueIfTrue(ifx);
6864 // lit == 0 => result = left
6865 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6867 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6870 if (AOP_TYPE(right) == AOP_CRY){
6871 if(pic16_sameRegs(AOP(result),AOP(left))){
6873 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6874 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6875 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6877 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6878 AOP(result)->aopu.aop_dir,
6879 AOP(result)->aopu.aop_dir);
6880 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6881 AOP(right)->aopu.aop_dir,
6882 AOP(right)->aopu.aop_dir);
6883 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6884 AOP(result)->aopu.aop_dir,
6885 AOP(result)->aopu.aop_dir);
6887 if( AOP_TYPE(result) == AOP_ACC) {
6888 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6889 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6890 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6891 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6895 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6896 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6897 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6898 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6900 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6901 AOP(result)->aopu.aop_dir,
6902 AOP(result)->aopu.aop_dir);
6903 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6904 AOP(right)->aopu.aop_dir,
6905 AOP(right)->aopu.aop_dir);
6906 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6907 AOP(left)->aopu.aop_dir,
6908 AOP(left)->aopu.aop_dir);
6909 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6910 AOP(result)->aopu.aop_dir,
6911 AOP(result)->aopu.aop_dir);
6916 symbol *tlbl = newiTempLabel(NULL);
6917 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6920 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6921 if( AOP_TYPE(right) == AOP_ACC) {
6922 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6924 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6925 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6930 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6931 pic16_emitcode(";XXX setb","c");
6932 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6933 AOP(left)->aopu.aop_dir,tlbl->key+100);
6934 pic16_toBoolean(right);
6935 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6936 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6937 jmpTrueOrFalse(ifx, tlbl);
6941 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6948 pic16_outBitC(result);
6950 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6951 genIfxJump(ifx, "c");
6955 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6956 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6957 if((AOP_TYPE(right) == AOP_LIT) &&
6958 (AOP_TYPE(result) == AOP_CRY) &&
6959 (AOP_TYPE(left) != AOP_CRY)){
6961 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6964 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6966 continueIfTrue(ifx);
6969 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6970 // lit = 0, result = boolean(left)
6972 pic16_emitcode(";XXX setb","c");
6973 pic16_toBoolean(right);
6975 symbol *tlbl = newiTempLabel(NULL);
6976 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6978 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6980 genIfxJump (ifx,"a");
6984 pic16_outBitC(result);
6988 /* if left is same as result */
6989 if(pic16_sameRegs(AOP(result),AOP(left))){
6991 for(;size--; offset++,lit>>=8) {
6992 if(AOP_TYPE(right) == AOP_LIT){
6993 if((lit & 0xff) == 0)
6994 /* or'ing with 0 has no effect */
6997 int p = my_powof2(lit & 0xff);
6999 /* only one bit is set in the literal, so use a bsf instruction */
7000 pic16_emitpcode(POC_BSF,
7001 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7003 if(know_W != (lit & 0xff))
7004 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7005 know_W = lit & 0xff;
7006 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7011 if (AOP_TYPE(left) == AOP_ACC) {
7012 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7013 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7015 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7016 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7018 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7019 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7025 // left & result in different registers
7026 if(AOP_TYPE(result) == AOP_CRY){
7028 // if(size), result in bit
7029 // if(!size && ifx), conditional oper: if(left | right)
7030 symbol *tlbl = newiTempLabel(NULL);
7031 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7032 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7036 pic16_emitcode(";XXX setb","c");
7038 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7039 pic16_emitcode(";XXX orl","a,%s",
7040 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7041 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7046 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7047 pic16_outBitC(result);
7049 jmpTrueOrFalse(ifx, tlbl);
7050 } else for(;(size--);offset++){
7052 // result = left & right
7053 if(AOP_TYPE(right) == AOP_LIT){
7054 int t = (lit >> (offset*8)) & 0x0FFL;
7057 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7058 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7060 pic16_emitcode("movf","%s,w",
7061 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7062 pic16_emitcode("movwf","%s",
7063 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7066 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7067 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7068 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7070 pic16_emitcode("movlw","0x%x",t);
7071 pic16_emitcode("iorwf","%s,w",
7072 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7073 pic16_emitcode("movwf","%s",
7074 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7080 // faster than result <- left, anl result,right
7081 // and better if result is SFR
7082 if (AOP_TYPE(left) == AOP_ACC) {
7083 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7084 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7086 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7087 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7089 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7090 pic16_emitcode("iorwf","%s,w",
7091 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7093 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7094 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7099 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7100 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7101 pic16_freeAsmop(result,NULL,ic,TRUE);
7104 /*-----------------------------------------------------------------*/
7105 /* genXor - code for xclusive or */
7106 /*-----------------------------------------------------------------*/
7107 static void genXor (iCode *ic, iCode *ifx)
7109 operand *left, *right, *result;
7111 unsigned long lit = 0L;
7113 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7115 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7116 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7117 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7119 /* if left is a literal & right is not ||
7120 if left needs acc & right does not */
7121 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7122 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7123 operand *tmp = right ;
7128 /* if result = right then exchange them */
7129 if(pic16_sameRegs(AOP(result),AOP(right))){
7130 operand *tmp = right ;
7135 /* if right is bit then exchange them */
7136 if (AOP_TYPE(right) == AOP_CRY &&
7137 AOP_TYPE(left) != AOP_CRY){
7138 operand *tmp = right ;
7142 if(AOP_TYPE(right) == AOP_LIT)
7143 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7145 size = AOP_SIZE(result);
7149 if (AOP_TYPE(left) == AOP_CRY){
7150 if(AOP_TYPE(right) == AOP_LIT){
7151 // c = bit & literal;
7153 // lit>>1 != 0 => result = 1
7154 if(AOP_TYPE(result) == AOP_CRY){
7156 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
7157 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7159 continueIfTrue(ifx);
7162 pic16_emitcode("setb","c");
7166 // lit == 0, result = left
7167 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7169 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7171 // lit == 1, result = not(left)
7172 if(size && pic16_sameRegs(AOP(result),AOP(left))){
7173 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
7174 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
7175 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7178 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7179 pic16_emitcode("cpl","c");
7186 symbol *tlbl = newiTempLabel(NULL);
7187 if (AOP_TYPE(right) == AOP_CRY){
7189 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7192 int sizer = AOP_SIZE(right);
7194 // if val>>1 != 0, result = 1
7195 pic16_emitcode("setb","c");
7197 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7199 // test the msb of the lsb
7200 pic16_emitcode("anl","a,#0xfe");
7201 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7205 pic16_emitcode("rrc","a");
7207 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7208 pic16_emitcode("cpl","c");
7209 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7214 pic16_outBitC(result);
7216 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7217 genIfxJump(ifx, "c");
7221 if(pic16_sameRegs(AOP(result),AOP(left))){
7222 /* if left is same as result */
7223 for(;size--; offset++) {
7224 if(AOP_TYPE(right) == AOP_LIT){
7225 int t = (lit >> (offset*8)) & 0x0FFL;
7229 if (IS_AOP_PREG(left)) {
7230 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7231 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7232 pic16_aopPut(AOP(result),"a",offset);
7234 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7235 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7236 pic16_emitcode("xrl","%s,%s",
7237 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7238 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7241 if (AOP_TYPE(left) == AOP_ACC)
7242 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7244 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7245 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7247 if (IS_AOP_PREG(left)) {
7248 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7249 pic16_aopPut(AOP(result),"a",offset);
7251 pic16_emitcode("xrl","%s,a",
7252 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7258 // left & result in different registers
7259 if(AOP_TYPE(result) == AOP_CRY){
7261 // if(size), result in bit
7262 // if(!size && ifx), conditional oper: if(left ^ right)
7263 symbol *tlbl = newiTempLabel(NULL);
7264 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7266 pic16_emitcode("setb","c");
7268 if((AOP_TYPE(right) == AOP_LIT) &&
7269 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7270 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7272 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7273 pic16_emitcode("xrl","a,%s",
7274 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7276 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7281 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7282 pic16_outBitC(result);
7284 jmpTrueOrFalse(ifx, tlbl);
7285 } else for(;(size--);offset++){
7287 // result = left & right
7288 if(AOP_TYPE(right) == AOP_LIT){
7289 int t = (lit >> (offset*8)) & 0x0FFL;
7292 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7293 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7294 pic16_emitcode("movf","%s,w",
7295 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7296 pic16_emitcode("movwf","%s",
7297 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7300 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7301 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7302 pic16_emitcode("comf","%s,w",
7303 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7304 pic16_emitcode("movwf","%s",
7305 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7308 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7309 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7310 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7311 pic16_emitcode("movlw","0x%x",t);
7312 pic16_emitcode("xorwf","%s,w",
7313 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7314 pic16_emitcode("movwf","%s",
7315 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7321 // faster than result <- left, anl result,right
7322 // and better if result is SFR
7323 if (AOP_TYPE(left) == AOP_ACC) {
7324 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7325 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7327 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7328 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7329 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7330 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7332 if ( AOP_TYPE(result) != AOP_ACC){
7333 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7334 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7340 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7341 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7342 pic16_freeAsmop(result,NULL,ic,TRUE);
7345 /*-----------------------------------------------------------------*/
7346 /* genInline - write the inline code out */
7347 /*-----------------------------------------------------------------*/
7348 static void genInline (iCode *ic)
7350 char *buffer, *bp, *bp1;
7352 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7354 _G.inLine += (!options.asmpeep);
7356 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7357 strcpy(buffer,IC_INLINE(ic));
7359 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7361 /* emit each line as a code */
7367 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7375 /* print label, use this special format with NULL directive
7376 * to denote that the argument should not be indented with tab */
7377 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7384 if ((bp1 != bp) && *bp1)
7385 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7390 _G.inLine -= (!options.asmpeep);
7393 /*-----------------------------------------------------------------*/
7394 /* genRRC - rotate right with carry */
7395 /*-----------------------------------------------------------------*/
7396 static void genRRC (iCode *ic)
7398 operand *left , *result ;
7399 int size, offset = 0, same;
7401 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7403 /* rotate right with carry */
7405 result=IC_RESULT(ic);
7406 pic16_aopOp (left,ic,FALSE);
7407 pic16_aopOp (result,ic,FALSE);
7409 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7411 same = pic16_sameRegs(AOP(result),AOP(left));
7413 size = AOP_SIZE(result);
7415 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7417 /* get the lsb and put it into the carry */
7418 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7425 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7427 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7428 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7434 pic16_freeAsmop(left,NULL,ic,TRUE);
7435 pic16_freeAsmop(result,NULL,ic,TRUE);
7438 /*-----------------------------------------------------------------*/
7439 /* genRLC - generate code for rotate left with carry */
7440 /*-----------------------------------------------------------------*/
7441 static void genRLC (iCode *ic)
7443 operand *left , *result ;
7444 int size, offset = 0;
7447 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7448 /* rotate right with carry */
7450 result=IC_RESULT(ic);
7451 pic16_aopOp (left,ic,FALSE);
7452 pic16_aopOp (result,ic,FALSE);
7454 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7456 same = pic16_sameRegs(AOP(result),AOP(left));
7458 /* move it to the result */
7459 size = AOP_SIZE(result);
7461 /* get the msb and put it into the carry */
7462 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7469 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7471 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7472 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7479 pic16_freeAsmop(left,NULL,ic,TRUE);
7480 pic16_freeAsmop(result,NULL,ic,TRUE);
7484 /* gpasm can get the highest order bit with HIGH/UPPER
7485 * so the following probably is not needed -- VR */
7487 /*-----------------------------------------------------------------*/
7488 /* genGetHbit - generates code get highest order bit */
7489 /*-----------------------------------------------------------------*/
7490 static void genGetHbit (iCode *ic)
7492 operand *left, *result;
7494 result=IC_RESULT(ic);
7495 pic16_aopOp (left,ic,FALSE);
7496 pic16_aopOp (result,ic,FALSE);
7498 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7499 /* get the highest order byte into a */
7500 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7501 if(AOP_TYPE(result) == AOP_CRY){
7502 pic16_emitcode("rlc","a");
7503 pic16_outBitC(result);
7506 pic16_emitcode("rl","a");
7507 pic16_emitcode("anl","a,#0x01");
7508 pic16_outAcc(result);
7512 pic16_freeAsmop(left,NULL,ic,TRUE);
7513 pic16_freeAsmop(result,NULL,ic,TRUE);
7517 /*-----------------------------------------------------------------*/
7518 /* AccRol - rotate left accumulator by known count */
7519 /*-----------------------------------------------------------------*/
7520 static void AccRol (int shCount)
7522 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7523 shCount &= 0x0007; // shCount : 0..7
7528 pic16_emitcode("rl","a");
7531 pic16_emitcode("rl","a");
7532 pic16_emitcode("rl","a");
7535 pic16_emitcode("swap","a");
7536 pic16_emitcode("rr","a");
7539 pic16_emitcode("swap","a");
7542 pic16_emitcode("swap","a");
7543 pic16_emitcode("rl","a");
7546 pic16_emitcode("rr","a");
7547 pic16_emitcode("rr","a");
7550 pic16_emitcode("rr","a");
7556 /*-----------------------------------------------------------------*/
7557 /* AccLsh - left shift accumulator by known count */
7558 /*-----------------------------------------------------------------*/
7559 static void AccLsh (int shCount)
7561 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7567 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7570 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7571 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7574 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7575 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7578 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7581 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7582 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7585 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7586 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7589 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7593 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7596 /*-----------------------------------------------------------------*/
7597 /* AccRsh - right shift accumulator by known count */
7598 /*-----------------------------------------------------------------*/
7599 static void AccRsh (int shCount, int andmask)
7601 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7606 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7607 // andmask = 0; /* no need */
7610 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7611 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7612 // andmask = 0; /* no need */
7615 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7616 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7619 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7622 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7623 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7626 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7627 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7630 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7635 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7637 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7641 /*-----------------------------------------------------------------*/
7642 /* AccSRsh - signed right shift accumulator by known count */
7643 /*-----------------------------------------------------------------*/
7644 static void AccSRsh (int shCount)
7647 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7650 pic16_emitcode("mov","c,acc.7");
7651 pic16_emitcode("rrc","a");
7652 } else if(shCount == 2){
7653 pic16_emitcode("mov","c,acc.7");
7654 pic16_emitcode("rrc","a");
7655 pic16_emitcode("mov","c,acc.7");
7656 pic16_emitcode("rrc","a");
7658 tlbl = newiTempLabel(NULL);
7659 /* rotate right accumulator */
7660 AccRol(8 - shCount);
7661 /* and kill the higher order bits */
7662 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7663 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7664 pic16_emitcode("orl","a,#0x%02x",
7665 (unsigned char)~SRMask[shCount]);
7666 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7671 /*-----------------------------------------------------------------*/
7672 /* shiftR1Left2Result - shift right one byte from left to result */
7673 /*-----------------------------------------------------------------*/
7674 static void shiftR1Left2ResultSigned (operand *left, int offl,
7675 operand *result, int offr,
7680 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7682 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7686 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7688 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7690 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7691 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7697 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7699 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7701 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7702 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7704 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7705 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7711 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7713 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7714 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7717 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7718 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7719 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7721 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7722 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7724 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7728 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7729 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7730 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7731 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
7732 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7736 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7738 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7739 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7741 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7742 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
7743 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7744 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
7745 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7750 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7751 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7752 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7753 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7754 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7755 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7757 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7758 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7759 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7760 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7761 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7767 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7768 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7769 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7770 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7772 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7773 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7774 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7782 /*-----------------------------------------------------------------*/
7783 /* shiftR1Left2Result - shift right one byte from left to result */
7784 /*-----------------------------------------------------------------*/
7785 static void shiftR1Left2Result (operand *left, int offl,
7786 operand *result, int offr,
7787 int shCount, int sign)
7791 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7793 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7795 /* Copy the msb into the carry if signed. */
7797 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7807 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7809 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7810 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7816 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7818 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7819 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7822 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7827 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7829 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7830 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7833 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7834 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7835 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7836 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7840 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7841 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7842 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7846 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7847 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7848 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7850 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7855 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7856 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7857 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7858 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7859 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7864 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7865 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7866 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7875 /*-----------------------------------------------------------------*/
7876 /* shiftL1Left2Result - shift left one byte from left to result */
7877 /*-----------------------------------------------------------------*/
7878 static void shiftL1Left2Result (operand *left, int offl,
7879 operand *result, int offr, int shCount)
7884 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7886 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7887 DEBUGpic16_emitcode ("; ***","same = %d",same);
7888 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7890 /* shift left accumulator */
7891 //AccLsh(shCount); // don't comment out just yet...
7892 // pic16_aopPut(AOP(result),"a",offr);
7896 /* Shift left 1 bit position */
7897 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7899 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7901 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7902 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7906 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7907 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7908 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7909 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7912 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7913 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7914 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7915 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7916 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7919 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7920 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7921 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7924 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7925 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7926 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7927 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7930 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7931 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7932 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7933 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7934 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7937 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7938 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7939 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7943 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7948 /*-----------------------------------------------------------------*/
7949 /* movLeft2Result - move byte from left to result */
7950 /*-----------------------------------------------------------------*/
7951 static void movLeft2Result (operand *left, int offl,
7952 operand *result, int offr)
7955 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7956 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7957 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7959 if (*l == '@' && (IS_AOP_PREG(result))) {
7960 pic16_emitcode("mov","a,%s",l);
7961 pic16_aopPut(AOP(result),"a",offr);
7963 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7964 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7969 /*-----------------------------------------------------------------*/
7970 /* shiftL2Left2Result - shift left two bytes from left to result */
7971 /*-----------------------------------------------------------------*/
7972 static void shiftL2Left2Result (operand *left, int offl,
7973 operand *result, int offr, int shCount)
7975 int same = pic16_sameRegs(AOP(result), AOP(left));
7978 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7980 if (same && (offl != offr)) { // shift bytes
7983 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7984 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7986 } else { // just treat as different later on
7999 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8000 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8001 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8005 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8006 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8012 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8013 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8014 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8015 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8016 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8017 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8018 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8020 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8021 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8025 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8026 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8027 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8028 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8029 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8030 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8031 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8032 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8033 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8034 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8037 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8038 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8039 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8040 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8041 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8051 /* note, use a mov/add for the shift since the mov has a
8052 chance of getting optimized out */
8053 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8054 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8055 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8056 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8057 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8061 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8062 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8068 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8069 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8070 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8071 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8072 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8073 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8074 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8075 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8079 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8080 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8084 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8085 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8086 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8087 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8089 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8090 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8091 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8092 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8093 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8094 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8095 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8096 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8099 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8100 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8101 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8102 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8103 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8108 /*-----------------------------------------------------------------*/
8109 /* shiftR2Left2Result - shift right two bytes from left to result */
8110 /*-----------------------------------------------------------------*/
8111 static void shiftR2Left2Result (operand *left, int offl,
8112 operand *result, int offr,
8113 int shCount, int sign)
8115 int same = pic16_sameRegs(AOP(result), AOP(left));
8117 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8119 if (same && (offl != offr)) { // shift right bytes
8122 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8123 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8125 } else { // just treat as different later on
8137 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8142 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8143 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8145 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8146 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8147 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8148 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8153 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8156 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8157 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8164 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
8165 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
8166 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8168 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8169 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
8170 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8171 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8173 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8174 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8175 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8177 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8178 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8179 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8180 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8181 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8185 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8186 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8190 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
8191 pic16_emitpcode(POC_BTFSC,
8192 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
8193 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8201 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8202 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8204 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8205 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8206 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8207 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8209 pic16_emitpcode(POC_BTFSC,
8210 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8211 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8213 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8214 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8215 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8216 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8218 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8219 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8220 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8221 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8222 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8223 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8224 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8225 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8227 pic16_emitpcode(POC_BTFSC,
8228 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8229 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8231 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8232 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8239 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8240 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8241 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8242 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8245 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8247 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8252 /*-----------------------------------------------------------------*/
8253 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8254 /*-----------------------------------------------------------------*/
8255 static void shiftLLeftOrResult (operand *left, int offl,
8256 operand *result, int offr, int shCount)
8258 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8260 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8261 /* shift left accumulator */
8263 /* or with result */
8264 /* back to result */
8265 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8268 /*-----------------------------------------------------------------*/
8269 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8270 /*-----------------------------------------------------------------*/
8271 static void shiftRLeftOrResult (operand *left, int offl,
8272 operand *result, int offr, int shCount)
8274 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8276 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8277 /* shift right accumulator */
8279 /* or with result */
8280 /* back to result */
8281 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8284 /*-----------------------------------------------------------------*/
8285 /* genlshOne - left shift a one byte quantity by known count */
8286 /*-----------------------------------------------------------------*/
8287 static void genlshOne (operand *result, operand *left, int shCount)
8289 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8290 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8293 /*-----------------------------------------------------------------*/
8294 /* genlshTwo - left shift two bytes by known amount != 0 */
8295 /*-----------------------------------------------------------------*/
8296 static void genlshTwo (operand *result,operand *left, int shCount)
8300 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8301 size = pic16_getDataSize(result);
8303 /* if shCount >= 8 */
8309 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8311 movLeft2Result(left, LSB, result, MSB16);
8313 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8316 /* 1 <= shCount <= 7 */
8319 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8321 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8325 /*-----------------------------------------------------------------*/
8326 /* shiftLLong - shift left one long from left to result */
8327 /* offr = LSB or MSB16 */
8328 /*-----------------------------------------------------------------*/
8329 static void shiftLLong (operand *left, operand *result, int offr )
8331 int size = AOP_SIZE(result);
8332 int same = pic16_sameRegs(AOP(left),AOP(result));
8335 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8337 if (same && (offr == MSB16)) { //shift one byte
8338 for(i=size-1;i>=MSB16;i--) {
8339 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8340 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8343 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8346 if (size >= LSB+offr ){
8348 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8350 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8351 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8355 if(size >= MSB16+offr){
8357 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8359 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8360 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8364 if(size >= MSB24+offr){
8366 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8368 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8369 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8373 if(size > MSB32+offr){
8375 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8377 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8378 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8382 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8386 /*-----------------------------------------------------------------*/
8387 /* genlshFour - shift four byte by a known amount != 0 */
8388 /*-----------------------------------------------------------------*/
8389 static void genlshFour (operand *result, operand *left, int shCount)
8393 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8394 size = AOP_SIZE(result);
8396 /* if shifting more that 3 bytes */
8397 if (shCount >= 24 ) {
8400 /* lowest order of left goes to the highest
8401 order of the destination */
8402 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8404 movLeft2Result(left, LSB, result, MSB32);
8406 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8407 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8408 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8413 /* more than two bytes */
8414 else if ( shCount >= 16 ) {
8415 /* lower order two bytes goes to higher order two bytes */
8417 /* if some more remaining */
8419 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8421 movLeft2Result(left, MSB16, result, MSB32);
8422 movLeft2Result(left, LSB, result, MSB24);
8424 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8425 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8429 /* if more than 1 byte */
8430 else if ( shCount >= 8 ) {
8431 /* lower order three bytes goes to higher order three bytes */
8435 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8437 movLeft2Result(left, LSB, result, MSB16);
8439 else{ /* size = 4 */
8441 movLeft2Result(left, MSB24, result, MSB32);
8442 movLeft2Result(left, MSB16, result, MSB24);
8443 movLeft2Result(left, LSB, result, MSB16);
8444 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8446 else if(shCount == 1)
8447 shiftLLong(left, result, MSB16);
8449 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8450 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8451 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8452 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8457 /* 1 <= shCount <= 7 */
8458 else if(shCount <= 3)
8460 shiftLLong(left, result, LSB);
8461 while(--shCount >= 1)
8462 shiftLLong(result, result, LSB);
8464 /* 3 <= shCount <= 7, optimize */
8466 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8467 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8468 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8472 /*-----------------------------------------------------------------*/
8473 /* genLeftShiftLiteral - left shifting by known count */
8474 /*-----------------------------------------------------------------*/
8475 static void genLeftShiftLiteral (operand *left,
8480 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8483 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8484 pic16_freeAsmop(right,NULL,ic,TRUE);
8486 pic16_aopOp(left,ic,FALSE);
8487 pic16_aopOp(result,ic,FALSE);
8489 size = getSize(operandType(result));
8492 pic16_emitcode("; shift left ","result %d, left %d",size,
8496 /* I suppose that the left size >= result size */
8499 movLeft2Result(left, size, result, size);
8503 else if(shCount >= (size * 8))
8505 pic16_aopPut(AOP(result),zero,size);
8509 genlshOne (result,left,shCount);
8514 genlshTwo (result,left,shCount);
8518 genlshFour (result,left,shCount);
8522 pic16_freeAsmop(left,NULL,ic,TRUE);
8523 pic16_freeAsmop(result,NULL,ic,TRUE);
8526 /*-----------------------------------------------------------------*
8527 * genMultiAsm - repeat assembly instruction for size of register.
8528 * if endian == 1, then the high byte (i.e base address + size of
8529 * register) is used first else the low byte is used first;
8530 *-----------------------------------------------------------------*/
8531 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8536 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8549 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
8554 /*-----------------------------------------------------------------*/
8555 /* genLeftShift - generates code for left shifting */
8556 /*-----------------------------------------------------------------*/
8557 static void genLeftShift (iCode *ic)
8559 operand *left,*right, *result;
8562 symbol *tlbl , *tlbl1;
8565 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8567 right = IC_RIGHT(ic);
8569 result = IC_RESULT(ic);
8571 pic16_aopOp(right,ic,FALSE);
8573 /* if the shift count is known then do it
8574 as efficiently as possible */
8575 if (AOP_TYPE(right) == AOP_LIT) {
8576 genLeftShiftLiteral (left,right,result,ic);
8580 /* shift count is unknown then we have to form
8581 a loop get the loop count in B : Note: we take
8582 only the lower order byte since shifting
8583 more that 32 bits make no sense anyway, ( the
8584 largest size of an object can be only 32 bits ) */
8587 pic16_aopOp(left,ic,FALSE);
8588 pic16_aopOp(result,ic,FALSE);
8590 /* now move the left to the result if they are not the
8592 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8593 AOP_SIZE(result) > 1) {
8595 size = AOP_SIZE(result);
8598 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8599 if (*l == '@' && (IS_AOP_PREG(result))) {
8601 pic16_emitcode("mov","a,%s",l);
8602 pic16_aopPut(AOP(result),"a",offset);
8604 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8605 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8606 //pic16_aopPut(AOP(result),l,offset);
8612 size = AOP_SIZE(result);
8614 /* if it is only one byte then */
8616 if(optimized_for_speed) {
8617 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8618 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8619 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8620 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8621 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8622 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8623 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8624 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
8625 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
8626 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
8627 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8628 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8631 tlbl = newiTempLabel(NULL);
8632 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8633 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8634 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8637 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8638 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8639 pic16_emitpLabel(tlbl->key);
8640 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8641 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8643 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8648 if (pic16_sameRegs(AOP(left),AOP(result))) {
8650 tlbl = newiTempLabel(NULL);
8651 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8652 genMultiAsm(POC_RRCF, result, size,1);
8653 pic16_emitpLabel(tlbl->key);
8654 genMultiAsm(POC_RLCF, result, size,0);
8655 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8657 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8661 //tlbl = newiTempLabel(NULL);
8663 //tlbl1 = newiTempLabel(NULL);
8665 //reAdjustPreg(AOP(result));
8667 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8668 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8669 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8671 //pic16_emitcode("add","a,acc");
8672 //pic16_aopPut(AOP(result),"a",offset++);
8674 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8676 // pic16_emitcode("rlc","a");
8677 // pic16_aopPut(AOP(result),"a",offset++);
8679 //reAdjustPreg(AOP(result));
8681 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8682 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8685 tlbl = newiTempLabel(NULL);
8686 tlbl1= newiTempLabel(NULL);
8688 size = AOP_SIZE(result);
8691 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8693 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8695 /* offset should be 0, 1 or 3 */
8697 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8699 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8701 pic16_emitpcode(POC_MOVWF, pctemp);
8704 pic16_emitpLabel(tlbl->key);
8707 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8709 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
8711 pic16_emitpcode(POC_DECFSZ, pctemp);
8712 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8713 pic16_emitpLabel(tlbl1->key);
8715 pic16_popReleaseTempReg(pctemp);
8719 pic16_freeAsmop (right,NULL,ic,TRUE);
8720 pic16_freeAsmop(left,NULL,ic,TRUE);
8721 pic16_freeAsmop(result,NULL,ic,TRUE);
8724 /*-----------------------------------------------------------------*/
8725 /* genrshOne - right shift a one byte quantity by known count */
8726 /*-----------------------------------------------------------------*/
8727 static void genrshOne (operand *result, operand *left,
8728 int shCount, int sign)
8730 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8731 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8734 /*-----------------------------------------------------------------*/
8735 /* genrshTwo - right shift two bytes by known amount != 0 */
8736 /*-----------------------------------------------------------------*/
8737 static void genrshTwo (operand *result,operand *left,
8738 int shCount, int sign)
8740 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8741 /* if shCount >= 8 */
8745 shiftR1Left2Result(left, MSB16, result, LSB,
8748 movLeft2Result(left, MSB16, result, LSB);
8750 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8753 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8754 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8758 /* 1 <= shCount <= 7 */
8760 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
8763 /*-----------------------------------------------------------------*/
8764 /* shiftRLong - shift right one long from left to result */
8765 /* offl = LSB or MSB16 */
8766 /*-----------------------------------------------------------------*/
8767 static void shiftRLong (operand *left, int offl,
8768 operand *result, int sign)
8770 int size = AOP_SIZE(result);
8771 int same = pic16_sameRegs(AOP(left),AOP(result));
8773 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8775 if (same && (offl == MSB16)) { //shift one byte right
8776 for(i=MSB16;i<size;i++) {
8777 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8778 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8783 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8789 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8791 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8792 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8796 /* add sign of "a" */
8797 pic16_addSign(result, MSB32, sign);
8801 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8803 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8804 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8808 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8810 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8811 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8815 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8818 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8819 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8824 /*-----------------------------------------------------------------*/
8825 /* genrshFour - shift four byte by a known amount != 0 */
8826 /*-----------------------------------------------------------------*/
8827 static void genrshFour (operand *result, operand *left,
8828 int shCount, int sign)
8830 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8831 /* if shifting more that 3 bytes */
8832 if(shCount >= 24 ) {
8835 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8837 movLeft2Result(left, MSB32, result, LSB);
8839 pic16_addSign(result, MSB16, sign);
8841 else if(shCount >= 16){
8844 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8846 movLeft2Result(left, MSB24, result, LSB);
8847 movLeft2Result(left, MSB32, result, MSB16);
8849 pic16_addSign(result, MSB24, sign);
8851 else if(shCount >= 8){
8854 shiftRLong(left, MSB16, result, sign);
8855 else if(shCount == 0){
8856 movLeft2Result(left, MSB16, result, LSB);
8857 movLeft2Result(left, MSB24, result, MSB16);
8858 movLeft2Result(left, MSB32, result, MSB24);
8859 pic16_addSign(result, MSB32, sign);
8861 else{ //shcount >= 2
8862 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8863 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8864 /* the last shift is signed */
8865 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8866 pic16_addSign(result, MSB32, sign);
8869 else{ /* 1 <= shCount <= 7 */
8871 shiftRLong(left, LSB, result, sign);
8873 shiftRLong(result, LSB, result, sign);
8876 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8877 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8878 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8883 /*-----------------------------------------------------------------*/
8884 /* genRightShiftLiteral - right shifting by known count */
8885 /*-----------------------------------------------------------------*/
8886 static void genRightShiftLiteral (operand *left,
8892 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8895 pic16_freeAsmop(right,NULL,ic,TRUE);
8897 pic16_aopOp(left,ic,FALSE);
8898 pic16_aopOp(result,ic,FALSE);
8900 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8903 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8907 lsize = pic16_getDataSize(left);
8908 res_size = pic16_getDataSize(result);
8909 /* test the LEFT size !!! */
8911 /* I suppose that the left size >= result size */
8914 movLeft2Result(left, lsize, result, res_size);
8917 else if(shCount >= (lsize * 8)){
8920 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8922 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8923 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8928 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8929 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8930 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8932 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8937 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8944 genrshOne (result,left,shCount,sign);
8948 genrshTwo (result,left,shCount,sign);
8952 genrshFour (result,left,shCount,sign);
8960 pic16_freeAsmop(left,NULL,ic,TRUE);
8961 pic16_freeAsmop(result,NULL,ic,TRUE);
8964 /*-----------------------------------------------------------------*/
8965 /* genSignedRightShift - right shift of signed number */
8966 /*-----------------------------------------------------------------*/
8967 static void genSignedRightShift (iCode *ic)
8969 operand *right, *left, *result;
8972 symbol *tlbl, *tlbl1 ;
8975 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8977 /* we do it the hard way put the shift count in b
8978 and loop thru preserving the sign */
8979 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8981 right = IC_RIGHT(ic);
8983 result = IC_RESULT(ic);
8985 pic16_aopOp(right,ic,FALSE);
8986 pic16_aopOp(left,ic,FALSE);
8987 pic16_aopOp(result,ic,FALSE);
8990 if ( AOP_TYPE(right) == AOP_LIT) {
8991 genRightShiftLiteral (left,right,result,ic,1);
8994 /* shift count is unknown then we have to form
8995 a loop get the loop count in B : Note: we take
8996 only the lower order byte since shifting
8997 more that 32 bits make no sense anyway, ( the
8998 largest size of an object can be only 32 bits ) */
9000 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9001 //pic16_emitcode("inc","b");
9002 //pic16_freeAsmop (right,NULL,ic,TRUE);
9003 //pic16_aopOp(left,ic,FALSE);
9004 //pic16_aopOp(result,ic,FALSE);
9006 /* now move the left to the result if they are not the
9008 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9009 AOP_SIZE(result) > 1) {
9011 size = AOP_SIZE(result);
9015 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9016 if (*l == '@' && IS_AOP_PREG(result)) {
9018 pic16_emitcode("mov","a,%s",l);
9019 pic16_aopPut(AOP(result),"a",offset);
9021 pic16_aopPut(AOP(result),l,offset);
9023 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
9024 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9030 /* mov the highest order bit to OVR */
9031 tlbl = newiTempLabel(NULL);
9032 tlbl1= newiTempLabel(NULL);
9034 size = AOP_SIZE(result);
9037 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
9039 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9041 /* offset should be 0, 1 or 3 */
9042 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
9044 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9046 pic16_emitpcode(POC_MOVWF, pctemp);
9049 pic16_emitpLabel(tlbl->key);
9051 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
9052 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
9055 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
9058 pic16_emitpcode(POC_DECFSZ, pctemp);
9059 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9060 pic16_emitpLabel(tlbl1->key);
9062 pic16_popReleaseTempReg(pctemp);
9064 size = AOP_SIZE(result);
9066 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
9067 pic16_emitcode("rlc","a");
9068 pic16_emitcode("mov","ov,c");
9069 /* if it is only one byte then */
9071 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9073 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9074 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9075 pic16_emitcode("mov","c,ov");
9076 pic16_emitcode("rrc","a");
9077 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9078 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9079 pic16_aopPut(AOP(result),"a",0);
9083 reAdjustPreg(AOP(result));
9084 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9085 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9086 pic16_emitcode("mov","c,ov");
9088 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9090 pic16_emitcode("rrc","a");
9091 pic16_aopPut(AOP(result),"a",offset--);
9093 reAdjustPreg(AOP(result));
9094 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9095 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9100 pic16_freeAsmop(left,NULL,ic,TRUE);
9101 pic16_freeAsmop(result,NULL,ic,TRUE);
9102 pic16_freeAsmop(right,NULL,ic,TRUE);
9105 /*-----------------------------------------------------------------*/
9106 /* genRightShift - generate code for right shifting */
9107 /*-----------------------------------------------------------------*/
9108 static void genRightShift (iCode *ic)
9110 operand *right, *left, *result;
9114 symbol *tlbl, *tlbl1 ;
9116 /* if signed then we do it the hard way preserve the
9117 sign bit moving it inwards */
9118 letype = getSpec(operandType(IC_LEFT(ic)));
9119 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9121 if (!SPEC_USIGN(letype)) {
9122 genSignedRightShift (ic);
9126 /* signed & unsigned types are treated the same : i.e. the
9127 signed is NOT propagated inwards : quoting from the
9128 ANSI - standard : "for E1 >> E2, is equivalent to division
9129 by 2**E2 if unsigned or if it has a non-negative value,
9130 otherwise the result is implementation defined ", MY definition
9131 is that the sign does not get propagated */
9133 right = IC_RIGHT(ic);
9135 result = IC_RESULT(ic);
9137 pic16_aopOp(right,ic,FALSE);
9139 /* if the shift count is known then do it
9140 as efficiently as possible */
9141 if (AOP_TYPE(right) == AOP_LIT) {
9142 genRightShiftLiteral (left,right,result,ic, 0);
9146 /* shift count is unknown then we have to form
9147 a loop get the loop count in B : Note: we take
9148 only the lower order byte since shifting
9149 more that 32 bits make no sense anyway, ( the
9150 largest size of an object can be only 32 bits ) */
9152 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9153 pic16_emitcode("inc","b");
9154 pic16_aopOp(left,ic,FALSE);
9155 pic16_aopOp(result,ic,FALSE);
9157 /* now move the left to the result if they are not the
9159 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9160 AOP_SIZE(result) > 1) {
9162 size = AOP_SIZE(result);
9165 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9166 if (*l == '@' && IS_AOP_PREG(result)) {
9168 pic16_emitcode("mov","a,%s",l);
9169 pic16_aopPut(AOP(result),"a",offset);
9171 pic16_aopPut(AOP(result),l,offset);
9176 tlbl = newiTempLabel(NULL);
9177 tlbl1= newiTempLabel(NULL);
9178 size = AOP_SIZE(result);
9181 /* if it is only one byte then */
9184 tlbl = newiTempLabel(NULL);
9185 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9186 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9187 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9190 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9191 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9192 pic16_emitpLabel(tlbl->key);
9193 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9194 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9196 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9201 reAdjustPreg(AOP(result));
9202 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9203 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9206 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9208 pic16_emitcode("rrc","a");
9209 pic16_aopPut(AOP(result),"a",offset--);
9211 reAdjustPreg(AOP(result));
9213 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9214 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9217 pic16_freeAsmop(left,NULL,ic,TRUE);
9218 pic16_freeAsmop (right,NULL,ic,TRUE);
9219 pic16_freeAsmop(result,NULL,ic,TRUE);
9222 /*-----------------------------------------------------------------*/
9223 /* genUnpackBits - generates code for unpacking bits */
9224 /*-----------------------------------------------------------------*/
9225 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
9232 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9233 etype = getSpec(operandType(result));
9235 /* read the first byte */
9242 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9245 pic16_emitcode("clr","a");
9246 pic16_emitcode("movc","a","@a+dptr");
9251 /* if we have bitdisplacement then it fits */
9252 /* into this byte completely or if length is */
9253 /* less than a byte */
9254 if ((shCnt = SPEC_BSTR(etype)) ||
9255 (SPEC_BLEN(etype) <= 8)) {
9257 /* shift right acc */
9260 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9261 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9263 /* VR -- normally I would use the following, but since we use the hack,
9264 * to avoid the masking from AccRsh, why not mask it right now? */
9267 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9270 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9276 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9277 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9280 /* bit field did not fit in a byte */
9281 rlen = SPEC_BLEN(etype) - 8;
9282 pic16_aopPut(AOP(result),"a",offset++);
9289 pic16_emitcode("inc","%s",rname);
9290 pic16_emitcode("mov","a,@%s",rname);
9294 pic16_emitcode("inc","%s",rname);
9295 pic16_emitcode("movx","a,@%s",rname);
9299 pic16_emitcode("inc","dptr");
9300 pic16_emitcode("movx","a,@dptr");
9304 pic16_emitcode("clr","a");
9305 pic16_emitcode("inc","dptr");
9306 pic16_emitcode("movc","a","@a+dptr");
9310 pic16_emitcode("inc","dptr");
9311 pic16_emitcode("lcall","__gptrget");
9316 /* if we are done */
9320 pic16_aopPut(AOP(result),"a",offset++);
9325 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9326 pic16_aopPut(AOP(result),"a",offset);
9333 static void genDataPointerGet(operand *left,
9337 int size, offset = 0, leoffset=0 ;
9339 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9340 pic16_aopOp(result, ic, FALSE);
9342 size = AOP_SIZE(result);
9343 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9347 /* The following tests may save a redudant movff instruction when
9348 * accessing unions */
9350 /* if they are the same */
9351 if (operandsEqu (left, result)) {
9352 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9358 /* if they are the same registers */
9359 if (pic16_sameRegs(AOP(left),AOP(result))) {
9360 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9366 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9367 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9368 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9375 if ( AOP_TYPE(left) == AOP_PCODE) {
9376 fprintf(stderr,"genDataPointerGet %s, %d\n",
9377 AOP(left)->aopu.pcop->name,
9378 (AOP(left)->aopu.pcop->type == PO_DIR)?
9379 PCOR(AOP(left)->aopu.pcop)->instance:
9380 PCOI(AOP(left)->aopu.pcop)->offset);
9384 if(AOP(left)->aopu.pcop->type == PO_DIR)
9385 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9387 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9390 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9392 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9393 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9394 mov2w(AOP(left), offset); // patch 8
9395 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9397 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9398 pic16_popGet(AOP(left), offset), //patch 8
9399 pic16_popGet(AOP(result), offset)));
9407 pic16_freeAsmop(result,NULL,ic,TRUE);
9410 void pic16_loadFSR0(operand *op)
9412 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9416 /*-----------------------------------------------------------------*/
9417 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
9418 /*-----------------------------------------------------------------*/
9419 static void genNearPointerGet (operand *left,
9424 //regs *preg = NULL ;
9425 sym_link *rtype, *retype;
9426 sym_link *ltype = operandType(left);
9428 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9429 rtype = operandType(result);
9430 retype= getSpec(rtype);
9432 pic16_aopOp(left,ic,FALSE);
9434 // pic16_DumpOp("(left)",left);
9435 // pic16_DumpOp("(result)",result);
9437 /* if left is rematerialisable and
9438 * result is not bit variable type and
9439 * the left is pointer to data space i.e
9440 * lower 128 bytes of space */
9441 if (AOP_TYPE(left) == AOP_PCODE
9442 && !IS_BITFIELD(retype)
9443 && DCL_TYPE(ltype) == POINTER) {
9445 genDataPointerGet (left,result,ic);
9446 pic16_freeAsmop(left, NULL, ic, TRUE);
9450 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9452 /* if the value is already in a pointer register
9453 * then don't need anything more */
9454 if (!AOP_INPREG(AOP(left))) {
9455 /* otherwise get a free pointer register */
9456 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9458 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9459 if( (AOP_TYPE(left) == AOP_PCODE)
9460 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9461 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9463 if(!IS_BITFIELD(retype))
9464 pic16_loadFSR0( left ); // patch 10
9466 // set up FSR0 with address from left
9467 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9468 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9472 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9474 pic16_aopOp (result,ic,FALSE);
9476 /* if bitfield then unpack the bits */
9477 if (IS_BITFIELD(retype))
9478 genUnpackBits (result, left, NULL, POINTER);
9480 /* we have can just get the values */
9481 int size = AOP_SIZE(result);
9484 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9487 /* fsr0 is loaded already -- VR */
9488 // pic16_loadFSR0( left );
9490 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9491 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9495 pic16_emitpcode(POC_MOVFF,
9496 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9497 pic16_popGet(AOP(result), offset++)));
9499 pic16_emitpcode(POC_MOVFF,
9500 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9501 pic16_popGet(AOP(result), offset++)));
9505 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9506 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9508 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9512 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9514 pic16_emitcode("mov","a,@%s",rname);
9515 pic16_aopPut(AOP(result),"a",offset);
9517 sprintf(buffer,"@%s",rname);
9518 pic16_aopPut(AOP(result),buffer,offset);
9522 pic16_emitcode("inc","%s",rname);
9527 /* now some housekeeping stuff */
9529 /* we had to allocate for this iCode */
9530 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9531 pic16_freeAsmop(NULL,aop,ic,TRUE);
9533 /* we did not allocate which means left
9534 already in a pointer register, then
9535 if size > 0 && this could be used again
9536 we have to point it back to where it
9538 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9539 if (AOP_SIZE(result) > 1 &&
9540 !OP_SYMBOL(left)->remat &&
9541 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9543 // int size = AOP_SIZE(result) - 1;
9545 // pic16_emitcode("dec","%s",rname);
9550 pic16_freeAsmop(left,NULL,ic,TRUE);
9551 pic16_freeAsmop(result,NULL,ic,TRUE);
9555 /*-----------------------------------------------------------------*/
9556 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
9557 /*-----------------------------------------------------------------*/
9558 static void genPagedPointerGet (operand *left,
9565 sym_link *rtype, *retype;
9567 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9569 rtype = operandType(result);
9570 retype= getSpec(rtype);
9572 pic16_aopOp(left,ic,FALSE);
9574 /* if the value is already in a pointer register
9575 then don't need anything more */
9576 if (!AOP_INPREG(AOP(left))) {
9577 /* otherwise get a free pointer register */
9579 preg = getFreePtr(ic,&aop,FALSE);
9580 pic16_emitcode("mov","%s,%s",
9582 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9583 rname = preg->name ;
9585 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9587 pic16_freeAsmop(left,NULL,ic,TRUE);
9588 pic16_aopOp (result,ic,FALSE);
9590 /* if bitfield then unpack the bits */
9591 if (IS_BITFIELD(retype))
9592 genUnpackBits (result,left,rname,PPOINTER);
9594 /* we have can just get the values */
9595 int size = AOP_SIZE(result);
9600 pic16_emitcode("movx","a,@%s",rname);
9601 pic16_aopPut(AOP(result),"a",offset);
9606 pic16_emitcode("inc","%s",rname);
9610 /* now some housekeeping stuff */
9612 /* we had to allocate for this iCode */
9613 pic16_freeAsmop(NULL,aop,ic,TRUE);
9615 /* we did not allocate which means left
9616 already in a pointer register, then
9617 if size > 0 && this could be used again
9618 we have to point it back to where it
9620 if (AOP_SIZE(result) > 1 &&
9621 !OP_SYMBOL(left)->remat &&
9622 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9624 int size = AOP_SIZE(result) - 1;
9626 pic16_emitcode("dec","%s",rname);
9631 pic16_freeAsmop(result,NULL,ic,TRUE);
9636 /*-----------------------------------------------------------------*/
9637 /* genFarPointerGet - gget value from far space */
9638 /*-----------------------------------------------------------------*/
9639 static void genFarPointerGet (operand *left,
9640 operand *result, iCode *ic)
9643 sym_link *retype = getSpec(operandType(result));
9645 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9647 pic16_aopOp(left,ic,FALSE);
9649 /* if the operand is already in dptr
9650 then we do nothing else we move the value to dptr */
9651 if (AOP_TYPE(left) != AOP_STR) {
9652 /* if this is remateriazable */
9653 if (AOP_TYPE(left) == AOP_IMMD)
9654 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9655 else { /* we need to get it byte by byte */
9656 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9657 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9658 if (options.model == MODEL_FLAT24)
9660 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9664 /* so dptr know contains the address */
9665 pic16_freeAsmop(left,NULL,ic,TRUE);
9666 pic16_aopOp(result,ic,FALSE);
9668 /* if bit then unpack */
9669 if (IS_BITFIELD(retype))
9670 genUnpackBits(result,left,"dptr",FPOINTER);
9672 size = AOP_SIZE(result);
9676 pic16_emitcode("movx","a,@dptr");
9677 pic16_aopPut(AOP(result),"a",offset++);
9679 pic16_emitcode("inc","dptr");
9683 pic16_freeAsmop(result,NULL,ic,TRUE);
9686 /*-----------------------------------------------------------------*/
9687 /* genCodePointerGet - get value from code space */
9688 /*-----------------------------------------------------------------*/
9689 static void genCodePointerGet (operand *left,
9690 operand *result, iCode *ic)
9693 sym_link *retype = getSpec(operandType(result));
9695 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9697 pic16_aopOp(left,ic,FALSE);
9699 /* if the operand is already in dptr
9700 then we do nothing else we move the value to dptr */
9701 if (AOP_TYPE(left) != AOP_STR) {
9702 /* if this is remateriazable */
9703 if (AOP_TYPE(left) == AOP_IMMD)
9704 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9705 else { /* we need to get it byte by byte */
9706 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9707 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9708 if (options.model == MODEL_FLAT24)
9710 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9714 /* so dptr know contains the address */
9715 pic16_freeAsmop(left,NULL,ic,TRUE);
9716 pic16_aopOp(result,ic,FALSE);
9718 /* if bit then unpack */
9719 if (IS_BITFIELD(retype))
9720 genUnpackBits(result,left,"dptr",CPOINTER);
9722 size = AOP_SIZE(result);
9726 pic16_emitcode("clr","a");
9727 pic16_emitcode("movc","a,@a+dptr");
9728 pic16_aopPut(AOP(result),"a",offset++);
9730 pic16_emitcode("inc","dptr");
9734 pic16_freeAsmop(result,NULL,ic,TRUE);
9737 /*-----------------------------------------------------------------*/
9738 /* genGenPointerGet - gget value from generic pointer space */
9739 /*-----------------------------------------------------------------*/
9740 static void genGenPointerGet (operand *left,
9741 operand *result, iCode *ic)
9743 int size, offset, lit;
9744 sym_link *retype = getSpec(operandType(result));
9746 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9747 pic16_aopOp(left,ic,FALSE);
9748 pic16_aopOp(result,ic,FALSE);
9749 size = AOP_SIZE(result);
9751 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9753 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9755 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9756 // load FSR0 from immediate
9757 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9759 // pic16_loadFSR0( left );
9764 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9766 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9773 else { /* we need to get it byte by byte */
9774 // set up FSR0 with address from left
9775 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9776 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9782 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9784 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9791 /* if bit then unpack */
9792 if (IS_BITFIELD(retype))
9793 genUnpackBits(result,left,"BAD",GPOINTER);
9796 pic16_freeAsmop(left,NULL,ic,TRUE);
9797 pic16_freeAsmop(result,NULL,ic,TRUE);
9801 /*-----------------------------------------------------------------*/
9802 /* genConstPointerGet - get value from const generic pointer space */
9803 /*-----------------------------------------------------------------*/
9804 static void genConstPointerGet (operand *left,
9805 operand *result, iCode *ic)
9807 //sym_link *retype = getSpec(operandType(result));
9808 // symbol *albl = newiTempLabel(NULL); // patch 15
9809 // symbol *blbl = newiTempLabel(NULL); //
9810 // PIC_OPCODE poc; // patch 15
9814 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9815 pic16_aopOp(left,ic,FALSE);
9816 pic16_aopOp(result,ic,TRUE);
9817 size = AOP_SIZE(result);
9819 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9821 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9823 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9824 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9825 pic16_emitpLabel(albl->key);
9827 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9829 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9830 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9831 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9832 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9833 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9835 pic16_emitpLabel(blbl->key);
9837 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9841 // set up table pointer
9842 if( (AOP_TYPE(left) == AOP_PCODE)
9843 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9844 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
9846 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9847 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9848 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9849 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9850 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9851 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9855 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9856 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9857 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9863 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9864 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9868 pic16_freeAsmop(left,NULL,ic,TRUE);
9869 pic16_freeAsmop(result,NULL,ic,TRUE);
9874 /*-----------------------------------------------------------------*/
9875 /* genPointerGet - generate code for pointer get */
9876 /*-----------------------------------------------------------------*/
9877 static void genPointerGet (iCode *ic)
9879 operand *left, *result ;
9880 sym_link *type, *etype;
9883 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9886 result = IC_RESULT(ic) ;
9888 /* depending on the type of pointer we need to
9889 move it to the correct pointer register */
9890 type = operandType(left);
9891 etype = getSpec(type);
9894 if (IS_PTR_CONST(type))
9896 if (IS_CODEPTR(type))
9898 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9900 /* if left is of type of pointer then it is simple */
9901 if (IS_PTR(type) && !IS_FUNC(type->next))
9902 p_type = DCL_TYPE(type);
9904 /* we have to go by the storage class */
9905 p_type = PTR_TYPE(SPEC_OCLS(etype));
9907 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9909 if (SPEC_OCLS(etype)->codesp ) {
9910 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9911 //p_type = CPOINTER ;
9914 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9915 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9916 /*p_type = FPOINTER ;*/
9918 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9919 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9920 /* p_type = PPOINTER; */
9922 if (SPEC_OCLS(etype) == idata )
9923 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9924 /* p_type = IPOINTER; */
9926 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9927 /* p_type = POINTER ; */
9930 /* now that we have the pointer type we assign
9931 the pointer values */
9936 genNearPointerGet (left,result,ic);
9940 genPagedPointerGet(left,result,ic);
9944 genFarPointerGet (left,result,ic);
9948 genConstPointerGet (left,result,ic);
9949 //pic16_emitcodePointerGet (left,result,ic);
9954 if (IS_PTR_CONST(type))
9955 genConstPointerGet (left,result,ic);
9958 genGenPointerGet (left,result,ic);
9962 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9963 "genPointerGet: illegal pointer type");
9969 /*-----------------------------------------------------------------*/
9970 /* genPackBits - generates code for packed bit storage */
9971 /*-----------------------------------------------------------------*/
9972 static void genPackBits (sym_link *etype , operand *result,
9974 char *rname, int p_type)
9982 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9983 blen = SPEC_BLEN(etype);
9984 bstr = SPEC_BSTR(etype);
9986 if(AOP_TYPE(right) == AOP_LIT) {
9987 if((blen == 1) && (bstr < 8)) {
9989 /* it is a single bit, so use the appropriate bit instructions */
9991 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9993 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9994 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9995 if((p_type == POINTER) && (result)) {
9996 /* workaround to reduce the extra lfsr instruction */
9998 pic16_emitpcode(POC_BSF,
9999 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10001 pic16_emitpcode(POC_BCF,
10002 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10007 pic16_emitpcode(POC_BSF,
10008 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10010 pic16_emitpcode(POC_BCF,
10011 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10018 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
10021 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
10023 /* if the bit lenth is less than or */
10024 /* it exactly fits a byte then */
10025 if((shCnt=SPEC_BSTR(etype))
10026 || SPEC_BLEN(etype) <= 8 ) {
10028 /* shift left acc */
10031 /* using PRODL as a temporary register here */
10032 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
10038 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10039 // pic16_emitcode ("mov","b,a");
10040 // pic16_emitcode("mov","a,@%s",rname);
10044 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10045 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
10046 (unsigned char)(0xff >> (8-bstr))) ));
10047 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
10048 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10055 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10056 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10061 if ( SPEC_BLEN(etype) <= 8 )
10064 pic16_emitcode("inc","%s",rname);
10065 rLen = SPEC_BLEN(etype) ;
10069 /* now generate for lengths greater than one byte */
10072 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
10082 pic16_emitcode("mov","@%s,a",rname);
10084 pic16_emitcode("mov","@%s,%s",rname,l);
10089 pic16_emitcode("movx","@dptr,a");
10094 DEBUGpic16_emitcode(";lcall","__gptrput");
10097 pic16_emitcode ("inc","%s",rname);
10102 /* last last was not complete */
10104 /* save the byte & read byte */
10107 pic16_emitcode ("mov","b,a");
10108 pic16_emitcode("mov","a,@%s",rname);
10112 pic16_emitcode ("mov","b,a");
10113 pic16_emitcode("movx","a,@dptr");
10117 pic16_emitcode ("push","b");
10118 pic16_emitcode ("push","acc");
10119 pic16_emitcode ("lcall","__gptrget");
10120 pic16_emitcode ("pop","b");
10124 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
10125 pic16_emitcode ("orl","a,b");
10128 if (p_type == GPOINTER)
10129 pic16_emitcode("pop","b");
10134 pic16_emitcode("mov","@%s,a",rname);
10138 pic16_emitcode("movx","@dptr,a");
10142 DEBUGpic16_emitcode(";lcall","__gptrput");
10146 /*-----------------------------------------------------------------*/
10147 /* genDataPointerSet - remat pointer to data space */
10148 /*-----------------------------------------------------------------*/
10149 static void genDataPointerSet(operand *right,
10153 int size, offset = 0, resoffset=0 ;
10155 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10156 pic16_aopOp(right,ic,FALSE);
10158 size = AOP_SIZE(right);
10160 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10163 if ( AOP_TYPE(result) == AOP_PCODE) {
10164 fprintf(stderr,"genDataPointerSet %s, %d\n",
10165 AOP(result)->aopu.pcop->name,
10166 (AOP(result)->aopu.pcop->type == PO_DIR)?
10167 PCOR(AOP(result)->aopu.pcop)->instance:
10168 PCOI(AOP(result)->aopu.pcop)->offset);
10172 if(AOP(result)->aopu.pcop->type == PO_DIR)
10173 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
10176 if (AOP_TYPE(right) == AOP_LIT) {
10177 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
10179 lit = lit >> (8*offset);
10181 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
10182 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
10184 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
10187 mov2w(AOP(right), offset);
10188 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
10194 pic16_freeAsmop(right,NULL,ic,TRUE);
10199 /*-----------------------------------------------------------------*/
10200 /* genNearPointerSet - pic16_emitcode for near pointer put */
10201 /*-----------------------------------------------------------------*/
10202 static void genNearPointerSet (operand *right,
10209 sym_link *ptype = operandType(result);
10210 sym_link *resetype;
10212 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10213 retype= getSpec(operandType(right));
10214 resetype = getSpec(operandType(result));
10216 pic16_aopOp(result,ic,FALSE);
10218 /* if the result is rematerializable &
10219 * in data space & not a bit variable */
10221 /* and result is not a bit variable */
10222 if (AOP_TYPE(result) == AOP_PCODE
10223 // && AOP_TYPE(result) == AOP_IMMD
10224 && DCL_TYPE(ptype) == POINTER
10225 && !IS_BITFIELD(retype)
10226 && !IS_BITFIELD(resetype)) {
10228 genDataPointerSet (right,result,ic);
10229 pic16_freeAsmop(result,NULL,ic,TRUE);
10233 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10234 pic16_aopOp(right,ic,FALSE);
10235 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10237 /* if the value is already in a pointer register
10238 * then don't need anything more */
10239 if (!AOP_INPREG(AOP(result))) {
10240 /* otherwise get a free pointer register */
10241 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10243 if( (AOP_TYPE(result) == AOP_PCODE)
10244 && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10245 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10247 if(!IS_BITFIELD(resetype))
10248 pic16_loadFSR0( result ); // patch 10
10250 // set up FSR0 with address of result
10251 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10252 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10257 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10259 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10261 /* if bitfield then unpack the bits */
10262 if (IS_BITFIELD(resetype)) {
10263 genPackBits (resetype, result, right, NULL, POINTER);
10265 /* we have can just get the values */
10266 int size = AOP_SIZE(right);
10269 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10271 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10274 //pic16_emitcode("mov","@%s,a",rname);
10275 pic16_emitcode("movf","indf0,w ;1");
10278 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
10279 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
10281 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
10283 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
10285 } else { // no literal //
10287 pic16_emitpcode(POC_MOVFF, //
10288 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10289 pic16_popCopyReg(&pic16_pc_postinc0))); //
10291 pic16_emitpcode(POC_MOVFF, //
10292 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10293 pic16_popCopyReg(&pic16_pc_indf0))); //
10301 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10302 /* now some housekeeping stuff */
10304 /* we had to allocate for this iCode */
10305 pic16_freeAsmop(NULL,aop,ic,TRUE);
10307 /* we did not allocate which means left
10308 * already in a pointer register, then
10309 * if size > 0 && this could be used again
10310 * we have to point it back to where it
10312 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10313 if (AOP_SIZE(right) > 1
10314 && !OP_SYMBOL(result)->remat
10315 && ( OP_SYMBOL(result)->liveTo > ic->seq
10318 int size = AOP_SIZE(right) - 1;
10321 pic16_emitcode("decf","fsr0,f");
10322 //pic16_emitcode("dec","%s",rname);
10326 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10329 pic16_freeAsmop(right,NULL,ic,TRUE);
10330 pic16_freeAsmop(result,NULL,ic,TRUE);
10333 /*-----------------------------------------------------------------*/
10334 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
10335 /*-----------------------------------------------------------------*/
10336 static void genPagedPointerSet (operand *right,
10341 regs *preg = NULL ;
10345 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10347 retype= getSpec(operandType(right));
10349 pic16_aopOp(result,ic,FALSE);
10351 /* if the value is already in a pointer register
10352 then don't need anything more */
10353 if (!AOP_INPREG(AOP(result))) {
10354 /* otherwise get a free pointer register */
10356 preg = getFreePtr(ic,&aop,FALSE);
10357 pic16_emitcode("mov","%s,%s",
10359 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10360 rname = preg->name ;
10362 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10364 pic16_freeAsmop(result,NULL,ic,TRUE);
10365 pic16_aopOp (right,ic,FALSE);
10367 /* if bitfield then unpack the bits */
10368 if (IS_BITFIELD(retype))
10369 genPackBits (retype,result,right,rname,PPOINTER);
10371 /* we have can just get the values */
10372 int size = AOP_SIZE(right);
10376 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10379 pic16_emitcode("movx","@%s,a",rname);
10382 pic16_emitcode("inc","%s",rname);
10388 /* now some housekeeping stuff */
10390 /* we had to allocate for this iCode */
10391 pic16_freeAsmop(NULL,aop,ic,TRUE);
10393 /* we did not allocate which means left
10394 already in a pointer register, then
10395 if size > 0 && this could be used again
10396 we have to point it back to where it
10398 if (AOP_SIZE(right) > 1 &&
10399 !OP_SYMBOL(result)->remat &&
10400 ( OP_SYMBOL(result)->liveTo > ic->seq ||
10402 int size = AOP_SIZE(right) - 1;
10404 pic16_emitcode("dec","%s",rname);
10409 pic16_freeAsmop(right,NULL,ic,TRUE);
10414 /*-----------------------------------------------------------------*/
10415 /* genFarPointerSet - set value from far space */
10416 /*-----------------------------------------------------------------*/
10417 static void genFarPointerSet (operand *right,
10418 operand *result, iCode *ic)
10421 sym_link *retype = getSpec(operandType(right));
10423 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10424 pic16_aopOp(result,ic,FALSE);
10426 /* if the operand is already in dptr
10427 then we do nothing else we move the value to dptr */
10428 if (AOP_TYPE(result) != AOP_STR) {
10429 /* if this is remateriazable */
10430 if (AOP_TYPE(result) == AOP_IMMD)
10431 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10432 else { /* we need to get it byte by byte */
10433 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10434 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10435 if (options.model == MODEL_FLAT24)
10437 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10441 /* so dptr know contains the address */
10442 pic16_freeAsmop(result,NULL,ic,TRUE);
10443 pic16_aopOp(right,ic,FALSE);
10445 /* if bit then unpack */
10446 if (IS_BITFIELD(retype))
10447 genPackBits(retype,result,right,"dptr",FPOINTER);
10449 size = AOP_SIZE(right);
10453 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10455 pic16_emitcode("movx","@dptr,a");
10457 pic16_emitcode("inc","dptr");
10461 pic16_freeAsmop(right,NULL,ic,TRUE);
10464 /*-----------------------------------------------------------------*/
10465 /* genGenPointerSet - set value from generic pointer space */
10466 /*-----------------------------------------------------------------*/
10467 static void genGenPointerSet (operand *right,
10468 operand *result, iCode *ic)
10470 int i, size, offset, lit;
10471 sym_link *retype = getSpec(operandType(right));
10473 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10475 pic16_aopOp(result,ic,FALSE);
10476 pic16_aopOp(right,ic,FALSE);
10477 size = AOP_SIZE(right);
10480 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10482 /* if the operand is already in dptr
10483 then we do nothing else we move the value to dptr */
10484 if (AOP_TYPE(result) != AOP_STR) {
10485 /* if this is remateriazable */
10486 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10487 // WARNING: anythig until "else" is untested!
10488 if (AOP_TYPE(result) == AOP_IMMD) {
10489 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10490 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10491 // load FSR0 from immediate
10492 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10496 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10498 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10504 else { /* we need to get it byte by byte */
10505 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10506 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10508 // set up FSR0 with address of result
10509 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10510 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10512 /* hack hack! see if this the FSR. If so don't load W */
10513 if(AOP_TYPE(right) != AOP_ACC) {
10515 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10517 if(AOP_TYPE(right) == AOP_LIT)
10520 // note: pic16_popGet handles sign extension
10521 for(i=0;i<size;i++) {
10522 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10524 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10526 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10531 for(i=0;i<size;i++) {
10533 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10534 pic16_popCopyReg(&pic16_pc_postinc0)));
10536 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10537 pic16_popCopyReg(&pic16_pc_indf0)));
10543 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10544 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10546 } // if (AOP_TYPE(result) != AOP_IMMD)
10548 } // if (AOP_TYPE(result) != AOP_STR)
10549 /* so dptr know contains the address */
10552 /* if bit then unpack */
10553 if (IS_BITFIELD(retype))
10554 genPackBits(retype,result,right,"dptr",GPOINTER);
10556 size = AOP_SIZE(right);
10559 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
10561 // set up FSR0 with address of result
10562 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10563 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10566 if (AOP_TYPE(right) == AOP_LIT) {
10567 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10569 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10571 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10573 } else { // no literal
10575 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10577 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10585 pic16_freeAsmop(right,NULL,ic,TRUE);
10586 pic16_freeAsmop(result,NULL,ic,TRUE);
10589 /*-----------------------------------------------------------------*/
10590 /* genPointerSet - stores the value into a pointer location */
10591 /*-----------------------------------------------------------------*/
10592 static void genPointerSet (iCode *ic)
10594 operand *right, *result ;
10595 sym_link *type, *etype;
10598 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10600 right = IC_RIGHT(ic);
10601 result = IC_RESULT(ic) ;
10603 /* depending on the type of pointer we need to
10604 move it to the correct pointer register */
10605 type = operandType(result);
10606 etype = getSpec(type);
10607 /* if left is of type of pointer then it is simple */
10608 if (IS_PTR(type) && !IS_FUNC(type->next)) {
10609 p_type = DCL_TYPE(type);
10612 /* we have to go by the storage class */
10613 p_type = PTR_TYPE(SPEC_OCLS(etype));
10615 /* if (SPEC_OCLS(etype)->codesp ) { */
10616 /* p_type = CPOINTER ; */
10619 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10620 /* p_type = FPOINTER ; */
10622 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10623 /* p_type = PPOINTER ; */
10625 /* if (SPEC_OCLS(etype) == idata ) */
10626 /* p_type = IPOINTER ; */
10628 /* p_type = POINTER ; */
10631 /* now that we have the pointer type we assign
10632 the pointer values */
10637 genNearPointerSet (right,result,ic);
10641 genPagedPointerSet (right,result,ic);
10645 genFarPointerSet (right,result,ic);
10649 genGenPointerSet (right,result,ic);
10653 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10654 "genPointerSet: illegal pointer type");
10658 /*-----------------------------------------------------------------*/
10659 /* genIfx - generate code for Ifx statement */
10660 /*-----------------------------------------------------------------*/
10661 static void genIfx (iCode *ic, iCode *popIc)
10663 operand *cond = IC_COND(ic);
10666 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10668 pic16_aopOp(cond,ic,FALSE);
10670 /* get the value into acc */
10671 if (AOP_TYPE(cond) != AOP_CRY)
10672 pic16_toBoolean(cond);
10675 /* the result is now in the accumulator */
10676 pic16_freeAsmop(cond,NULL,ic,TRUE);
10678 /* if there was something to be popped then do it */
10682 /* if the condition is a bit variable */
10683 if (isbit && IS_ITEMP(cond) &&
10685 genIfxJump(ic,SPIL_LOC(cond)->rname);
10686 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10689 if (isbit && !IS_ITEMP(cond))
10690 genIfxJump(ic,OP_SYMBOL(cond)->rname);
10692 genIfxJump(ic,"a");
10698 /*-----------------------------------------------------------------*/
10699 /* genAddrOf - generates code for address of */
10700 /*-----------------------------------------------------------------*/
10701 static void genAddrOf (iCode *ic)
10703 operand *result, *left;
10705 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
10706 pCodeOp *pcop0, *pcop1, *pcop2;
10708 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10710 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10711 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10713 sym = OP_SYMBOL( left );
10715 size = AOP_SIZE(IC_RESULT(ic));
10719 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
10724 // if(pic16_debug_verbose) {
10725 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10726 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10729 /* Assume that what we want the address of is in data space
10730 * since there is no stack on the PIC, yet! -- VR */
10732 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10735 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10738 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10742 pic16_emitpcode(POC_MOVLW, pcop0);
10743 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10744 pic16_emitpcode(POC_MOVLW, pcop1);
10745 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10746 pic16_emitpcode(POC_MOVLW, pcop2);
10747 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10750 pic16_emitpcode(POC_MOVLW, pcop0);
10751 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10752 pic16_emitpcode(POC_MOVLW, pcop1);
10753 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10755 pic16_emitpcode(POC_MOVLW, pcop0);
10756 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10759 pic16_freeAsmop(result,NULL,ic,TRUE);
10760 pic16_freeAsmop(left, NULL, ic, FALSE);
10765 /*-----------------------------------------------------------------*/
10766 /* genFarFarAssign - assignment when both are in far space */
10767 /*-----------------------------------------------------------------*/
10768 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10770 int size = AOP_SIZE(right);
10773 /* first push the right side on to the stack */
10775 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10777 pic16_emitcode ("push","acc");
10780 pic16_freeAsmop(right,NULL,ic,FALSE);
10781 /* now assign DPTR to result */
10782 pic16_aopOp(result,ic,FALSE);
10783 size = AOP_SIZE(result);
10785 pic16_emitcode ("pop","acc");
10786 pic16_aopPut(AOP(result),"a",--offset);
10788 pic16_freeAsmop(result,NULL,ic,FALSE);
10793 /*-----------------------------------------------------------------*/
10794 /* genAssign - generate code for assignment */
10795 /*-----------------------------------------------------------------*/
10796 static void genAssign (iCode *ic)
10798 operand *result, *right;
10799 int size, offset,know_W;
10800 unsigned long lit = 0L;
10802 result = IC_RESULT(ic);
10803 right = IC_RIGHT(ic) ;
10805 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10807 /* if they are the same */
10808 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10811 pic16_aopOp(right,ic,FALSE);
10812 pic16_aopOp(result,ic,TRUE);
10814 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10816 /* if they are the same registers */
10817 if (pic16_sameRegs(AOP(right),AOP(result)))
10820 /* if the result is a bit */
10821 if (AOP_TYPE(result) == AOP_CRY) {
10822 /* if the right size is a literal then
10823 we know what the value is */
10824 if (AOP_TYPE(right) == AOP_LIT) {
10826 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10827 pic16_popGet(AOP(result),0));
10829 if (((int) operandLitValue(right)))
10830 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10831 AOP(result)->aopu.aop_dir,
10832 AOP(result)->aopu.aop_dir);
10834 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10835 AOP(result)->aopu.aop_dir,
10836 AOP(result)->aopu.aop_dir);
10840 /* the right is also a bit variable */
10841 if (AOP_TYPE(right) == AOP_CRY) {
10842 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10843 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10844 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10846 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10847 AOP(result)->aopu.aop_dir,
10848 AOP(result)->aopu.aop_dir);
10849 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10850 AOP(right)->aopu.aop_dir,
10851 AOP(right)->aopu.aop_dir);
10852 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10853 AOP(result)->aopu.aop_dir,
10854 AOP(result)->aopu.aop_dir);
10858 /* we need to or */
10859 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10860 pic16_toBoolean(right);
10862 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10863 //pic16_aopPut(AOP(result),"a",0);
10867 /* bit variables done */
10869 size = AOP_SIZE(result);
10872 if(AOP_TYPE(right) == AOP_LIT) {
10873 if(!IS_FLOAT(operandType( right )))
10874 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10877 unsigned long lit_int;
10881 /* take care if literal is a float */
10882 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10883 lit = info.lit_int;
10887 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10888 // sizeof(unsigned long int), sizeof(float));
10890 if(AOP_TYPE(right) != AOP_LIT
10891 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10892 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10893 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
10895 // set up table pointer
10896 if( (AOP_TYPE(right) == AOP_PCODE)
10897 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10898 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10900 fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
10901 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10902 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10903 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10904 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10905 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10906 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10908 fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
10909 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10910 pic16_popCopyReg(&pic16_pc_tblptrl)));
10911 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10912 pic16_popCopyReg(&pic16_pc_tblptrh)));
10913 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10914 pic16_popCopyReg(&pic16_pc_tblptru)));
10917 size = min(AOP_SIZE(right), AOP_SIZE(result));
10919 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10920 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10921 pic16_popGet(AOP(result),offset)));
10925 if(AOP_SIZE(result) > AOP_SIZE(right)) {
10926 size = AOP_SIZE(result) - AOP_SIZE(right);
10928 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10938 /* VR - What is this?! */
10939 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10940 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10941 if(aopIdx(AOP(result),0) == 4) {
10943 /* this is a workaround to save value of right into wreg too,
10944 * value of wreg is going to be used later */
10945 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10946 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10947 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10951 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10957 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10958 if(AOP_TYPE(right) == AOP_LIT) {
10960 if(know_W != (lit&0xff))
10961 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10963 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10965 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10969 } else if (AOP_TYPE(right) == AOP_CRY) {
10970 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10972 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10973 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10975 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10976 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10977 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10979 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10982 /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10983 normally should work, but mind that the W register live range
10984 is not checked, so if the code generator assumes that the W
10985 is already loaded after such a pair, wrong code will be generated.
10987 Checking the live range is the next step.
10988 This is experimental code yet and has not been fully tested yet.
10989 USE WITH CARE. Revert to old code by setting 0 to the condition above.
10990 Vangelis Rokas 030603 (vrokas@otenet.gr) */
10992 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10994 /* This is the old code, which is assumed(?!) that works fine(!?) */
10996 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10997 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11006 pic16_freeAsmop (right,NULL,ic,FALSE);
11007 pic16_freeAsmop (result,NULL,ic,TRUE);
11010 /*-----------------------------------------------------------------*/
11011 /* genJumpTab - generates code for jump table */
11012 /*-----------------------------------------------------------------*/
11013 static void genJumpTab (iCode *ic)
11018 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11020 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
11021 /* get the condition into accumulator */
11022 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
11024 /* multiply by three */
11025 pic16_emitcode("add","a,acc");
11026 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
11028 jtab = newiTempLabel(NULL);
11029 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
11030 pic16_emitcode("jmp","@a+dptr");
11031 pic16_emitcode("","%05d_DS_:",jtab->key+100);
11033 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
11034 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
11036 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
11037 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
11038 pic16_emitpLabel(jtab->key);
11040 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
11042 /* now generate the jump labels */
11043 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
11044 jtab = setNextItem(IC_JTLABELS(ic))) {
11045 pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
11046 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
11052 /*-----------------------------------------------------------------*/
11053 /* genMixedOperation - gen code for operators between mixed types */
11054 /*-----------------------------------------------------------------*/
11056 TSD - Written for the PIC port - but this unfortunately is buggy.
11057 This routine is good in that it is able to efficiently promote
11058 types to different (larger) sizes. Unfortunately, the temporary
11059 variables that are optimized out by this routine are sometimes
11060 used in other places. So until I know how to really parse the
11061 iCode tree, I'm going to not be using this routine :(.
11063 static int genMixedOperation (iCode *ic)
11066 operand *result = IC_RESULT(ic);
11067 sym_link *ctype = operandType(IC_LEFT(ic));
11068 operand *right = IC_RIGHT(ic);
11074 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
11076 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11082 nextright = IC_RIGHT(nextic);
11083 nextleft = IC_LEFT(nextic);
11084 nextresult = IC_RESULT(nextic);
11086 pic16_aopOp(right,ic,FALSE);
11087 pic16_aopOp(result,ic,FALSE);
11088 pic16_aopOp(nextright, nextic, FALSE);
11089 pic16_aopOp(nextleft, nextic, FALSE);
11090 pic16_aopOp(nextresult, nextic, FALSE);
11092 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
11094 operand *t = right;
11098 pic16_emitcode(";remove right +","");
11100 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
11102 operand *t = right;
11106 pic16_emitcode(";remove left +","");
11110 big = AOP_SIZE(nextleft);
11111 small = AOP_SIZE(nextright);
11113 switch(nextic->op) {
11116 pic16_emitcode(";optimize a +","");
11117 /* if unsigned or not an integral type */
11118 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
11119 pic16_emitcode(";add a bit to something","");
11122 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
11124 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
11125 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
11126 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
11128 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
11136 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11137 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11138 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11141 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11143 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11144 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
11145 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
11146 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11147 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
11150 pic16_emitcode("rlf","known_zero,w");
11157 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11158 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11159 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11161 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11171 pic16_freeAsmop(right,NULL,ic,TRUE);
11172 pic16_freeAsmop(result,NULL,ic,TRUE);
11173 pic16_freeAsmop(nextright,NULL,ic,TRUE);
11174 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
11176 nextic->generated = 1;
11183 /*-----------------------------------------------------------------*/
11184 /* genCast - gen code for casting */
11185 /*-----------------------------------------------------------------*/
11186 static void genCast (iCode *ic)
11188 operand *result = IC_RESULT(ic);
11189 sym_link *ctype = operandType(IC_LEFT(ic));
11190 sym_link *rtype = operandType(IC_RIGHT(ic));
11191 operand *right = IC_RIGHT(ic);
11194 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11195 /* if they are equivalent then do nothing */
11196 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
11199 pic16_aopOp(right,ic,FALSE) ;
11200 pic16_aopOp(result,ic,FALSE);
11202 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11204 /* if the result is a bit */
11205 if (AOP_TYPE(result) == AOP_CRY) {
11207 /* if the right size is a literal then
11208 * we know what the value is */
11209 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11211 if (AOP_TYPE(right) == AOP_LIT) {
11212 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11213 pic16_popGet(AOP(result),0));
11215 if (((int) operandLitValue(right)))
11216 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
11217 AOP(result)->aopu.aop_dir,
11218 AOP(result)->aopu.aop_dir);
11220 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
11221 AOP(result)->aopu.aop_dir,
11222 AOP(result)->aopu.aop_dir);
11226 /* the right is also a bit variable */
11227 if (AOP_TYPE(right) == AOP_CRY) {
11229 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11231 pic16_emitcode("clrc","");
11232 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11233 AOP(right)->aopu.aop_dir,
11234 AOP(right)->aopu.aop_dir);
11235 pic16_aopPut(AOP(result),"c",0);
11239 /* we need to or */
11240 if (AOP_TYPE(right) == AOP_REG) {
11241 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
11242 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
11243 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
11245 pic16_toBoolean(right);
11246 pic16_aopPut(AOP(result),"a",0);
11250 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11253 size = AOP_SIZE(result);
11255 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11257 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
11258 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11259 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
11262 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11267 /* if they are the same size : or less */
11268 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11270 /* if they are in the same place */
11271 if (pic16_sameRegs(AOP(right),AOP(result)))
11274 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11276 if (IS_PTR_CONST(rtype))
11278 if (IS_CODEPTR(rtype))
11280 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11283 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11285 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11287 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11290 if(AOP_TYPE(right) == AOP_IMMD) {
11291 pCodeOp *pcop0, *pcop1, *pcop2;
11292 symbol *sym = OP_SYMBOL( right );
11294 size = AOP_SIZE(result);
11296 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11298 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11300 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11303 pic16_emitpcode(POC_MOVLW, pcop0);
11304 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11305 pic16_emitpcode(POC_MOVLW, pcop1);
11306 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11307 pic16_emitpcode(POC_MOVLW, pcop2);
11308 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11311 pic16_emitpcode(POC_MOVLW, pcop0);
11312 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11313 pic16_emitpcode(POC_MOVLW, pcop1);
11314 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11316 pic16_emitpcode(POC_MOVLW, pcop0);
11317 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11321 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11322 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11323 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11324 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11325 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11326 if(AOP_SIZE(result) <2)
11327 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11329 /* if they in different places then copy */
11330 size = AOP_SIZE(result);
11333 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11334 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11341 /* if the result is of type pointer */
11342 if (IS_PTR(ctype)) {
11344 sym_link *type = operandType(right);
11345 sym_link *etype = getSpec(type);
11347 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
11349 /* pointer to generic pointer */
11350 if (IS_GENPTR(ctype)) {
11354 p_type = DCL_TYPE(type);
11356 /* we have to go by the storage class */
11357 p_type = PTR_TYPE(SPEC_OCLS(etype));
11359 /* if (SPEC_OCLS(etype)->codesp ) */
11360 /* p_type = CPOINTER ; */
11362 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11363 /* p_type = FPOINTER ; */
11365 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11366 /* p_type = PPOINTER; */
11368 /* if (SPEC_OCLS(etype) == idata ) */
11369 /* p_type = IPOINTER ; */
11371 /* p_type = POINTER ; */
11374 /* the first two bytes are known */
11375 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
11376 size = GPTRSIZE - 1;
11379 if(offset < AOP_SIZE(right)) {
11380 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
11381 if ((AOP_TYPE(right) == AOP_PCODE) &&
11382 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11383 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11384 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11386 pic16_aopPut(AOP(result),
11387 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11391 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11394 /* the last byte depending on type */
11398 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11401 pic16_emitcode(";BUG!? ","%d",__LINE__);
11405 pic16_emitcode(";BUG!? ","%d",__LINE__);
11409 pic16_emitcode(";BUG!? ","%d",__LINE__);
11414 /* this should never happen */
11415 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11416 "got unknown pointer type");
11419 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
11423 /* just copy the pointers */
11424 size = AOP_SIZE(result);
11427 pic16_aopPut(AOP(result),
11428 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11437 /* so we now know that the size of destination is greater
11438 than the size of the source.
11439 Now, if the next iCode is an operator then we might be
11440 able to optimize the operation without performing a cast.
11442 if(genMixedOperation(ic))
11445 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11447 /* we move to result for the size of source */
11448 size = AOP_SIZE(right);
11451 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11452 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11453 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11457 /* now depending on the sign of the destination */
11458 size = AOP_SIZE(result) - AOP_SIZE(right);
11459 /* if unsigned or not an integral type */
11460 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11462 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11464 /* we need to extend the sign :( */
11467 /* Save one instruction of casting char to int */
11468 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11469 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11470 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
11472 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11475 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11477 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11479 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
11482 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
11487 pic16_freeAsmop(right,NULL,ic,TRUE);
11488 pic16_freeAsmop(result,NULL,ic,TRUE);
11492 /*-----------------------------------------------------------------*/
11493 /* genDjnz - generate decrement & jump if not zero instrucion */
11494 /*-----------------------------------------------------------------*/
11495 static int genDjnz (iCode *ic, iCode *ifx)
11497 symbol *lbl, *lbl1;
11498 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11503 /* if the if condition has a false label
11504 then we cannot save */
11508 /* if the minus is not of the form
11510 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11511 !IS_OP_LITERAL(IC_RIGHT(ic)))
11514 if (operandLitValue(IC_RIGHT(ic)) != 1)
11517 /* if the size of this greater than one then no
11519 if (getSize(operandType(IC_RESULT(ic))) > 1)
11522 /* otherwise we can save BIG */
11523 lbl = newiTempLabel(NULL);
11524 lbl1= newiTempLabel(NULL);
11526 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11528 if (IS_AOP_PREG(IC_RESULT(ic))) {
11529 pic16_emitcode("dec","%s",
11530 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11531 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11532 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11536 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11537 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11539 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11540 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
11543 /* pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11544 /* pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11545 /* pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11546 /* pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11549 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11550 ifx->generated = 1;
11554 /*-----------------------------------------------------------------*/
11555 /* genReceive - generate code for a receive iCode */
11556 /*-----------------------------------------------------------------*/
11557 static void genReceive (iCode *ic)
11559 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11562 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11563 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
11565 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11567 if (isOperandInFarSpace(IC_RESULT(ic)) &&
11568 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11569 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11571 int size = getSize(operandType(IC_RESULT(ic)));
11572 int offset = pic16_fReturnSizePic - size;
11576 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11577 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11581 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
11583 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11584 size = AOP_SIZE(IC_RESULT(ic));
11587 pic16_emitcode ("pop","acc");
11588 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11591 DEBUGpic16_emitcode ("; ***","2 %s %d",__FUNCTION__,__LINE__);
11594 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11596 assignResultValue(IC_RESULT(ic), 0);
11599 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11602 /*-----------------------------------------------------------------*/
11603 /* genDummyRead - generate code for dummy read of volatiles */
11604 /*-----------------------------------------------------------------*/
11606 genDummyRead (iCode * ic)
11608 pic16_emitcode ("; genDummyRead","");
11609 pic16_emitcode ("; not implemented","");
11614 /*-----------------------------------------------------------------*/
11615 /* genpic16Code - generate code for pic16 based controllers */
11616 /*-----------------------------------------------------------------*/
11618 * At this point, ralloc.c has gone through the iCode and attempted
11619 * to optimize in a way suitable for a PIC. Now we've got to generate
11620 * PIC instructions that correspond to the iCode.
11622 * Once the instructions are generated, we'll pass through both the
11623 * peep hole optimizer and the pCode optimizer.
11624 *-----------------------------------------------------------------*/
11626 void genpic16Code (iCode *lic)
11631 lineHead = lineCurr = NULL;
11633 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11634 pic16_addpBlock(pb);
11637 /* if debug information required */
11638 if (options.debug && currFunc) {
11640 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11645 for (ic = lic ; ic ; ic = ic->next ) {
11647 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11648 if ( cln != ic->lineno ) {
11649 if ( options.debug ) {
11650 debugFile->writeCLine (ic);
11653 if(!options.noCcodeInAsm) {
11654 pic16_addpCode2pBlock(pb,
11655 pic16_newpCodeCSource(ic->lineno, ic->filename,
11656 printCLine(ic->filename, ic->lineno)));
11662 if(options.iCodeInAsm) {
11664 /* insert here code to print iCode as comment */
11665 l = Safe_strdup(printILine(ic));
11666 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11669 /* if the result is marked as
11670 spilt and rematerializable or code for
11671 this has already been generated then
11673 if (resultRemat(ic) || ic->generated )
11676 /* depending on the operation */
11695 /* IPOP happens only when trying to restore a
11696 spilt live range, if there is an ifx statement
11697 following this pop then the if statement might
11698 be using some of the registers being popped which
11699 would destroy the contents of the register so
11700 we need to check for this condition and handle it */
11702 ic->next->op == IFX &&
11703 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
11704 genIfx (ic->next,ic);
11722 genEndFunction (ic);
11738 pic16_genPlus (ic) ;
11742 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11743 pic16_genMinus (ic);
11759 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
11763 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11770 /* note these two are xlated by algebraic equivalence
11771 during parsing SDCC.y */
11772 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11773 "got '>=' or '<=' shouldn't have come here");
11777 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11789 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11793 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11797 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11821 genRightShift (ic);
11824 case GET_VALUE_AT_ADDRESS:
11829 if (POINTER_SET(ic))
11856 addSet(&_G.sendSet,ic);
11859 case DUMMY_READ_VOLATILE:
11869 /* now we are ready to call the
11870 peep hole optimizer */
11871 if (!options.nopeep) {
11872 peepHole (&lineHead);
11874 /* now do the actual printing */
11875 printLine (lineHead,codeOutFile);
11878 DFPRINTF((stderr,"printing pBlock\n\n"));
11879 pic16_printpBlock(stdout,pb);