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);
6612 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
6614 /* patch provided by Aaron Colwell */
6615 if((posbit = isLiteralBit(bytelit)) != 0) {
6616 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
6617 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
6618 (posbit-1),0, PO_GPR_REGISTER));
6620 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
6622 if (bytelit == 0xff) {
6623 /* Aaron had a MOVF instruction here, changed to MOVFW cause
6624 * a peephole could optimize it out -- VR */
6625 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6627 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6628 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
6631 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
6632 pic16_popGetLabel(tlbl->key));
6636 /* old code, left here for reference -- VR 09/2004 */
6637 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6639 if((posbit = isLiteralBit(bytelit)) != 0)
6640 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6642 if(bytelit != 0x0FFL)
6643 pic16_emitcode("anl","a,%s",
6644 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6645 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6651 // bit = left & literal
6654 pic16_emitpLabel(tlbl->key);
6656 // if(left & literal)
6659 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
6660 pic16_emitpLabel(tlbl->key);
6667 pic16_outBitC(result);
6671 /* if left is same as result */
6672 if(pic16_sameRegs(AOP(result),AOP(left))){
6674 for(;size--; offset++,lit>>=8) {
6675 if(AOP_TYPE(right) == AOP_LIT){
6676 switch(lit & 0xff) {
6678 /* and'ing with 0 has clears the result */
6679 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6680 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6683 /* and'ing with 0xff is a nop when the result and left are the same */
6688 int p = my_powof2( (~lit) & 0xff );
6690 /* only one bit is set in the literal, so use a bcf instruction */
6691 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6692 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6695 pic16_emitcode("movlw","0x%x", (lit & 0xff));
6696 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6697 if(know_W != (lit&0xff))
6698 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6700 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6705 if (AOP_TYPE(left) == AOP_ACC) {
6706 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6708 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6709 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6716 // left & result in different registers
6717 if(AOP_TYPE(result) == AOP_CRY){
6719 // if(size), result in bit
6720 // if(!size && ifx), conditional oper: if(left & right)
6721 symbol *tlbl = newiTempLabel(NULL);
6722 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6724 pic16_emitcode("setb","c");
6726 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6727 pic16_emitcode("anl","a,%s",
6728 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6729 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6734 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6735 pic16_outBitC(result);
6737 jmpTrueOrFalse(ifx, tlbl);
6739 for(;(size--);offset++) {
6741 // result = left & right
6742 if(AOP_TYPE(right) == AOP_LIT){
6743 int t = (lit >> (offset*8)) & 0x0FFL;
6746 pic16_emitcode("clrf","%s",
6747 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6748 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6751 pic16_emitcode("movf","%s,w",
6752 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6753 pic16_emitcode("movwf","%s",
6754 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6755 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6756 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6759 pic16_emitcode("movlw","0x%x",t);
6760 pic16_emitcode("andwf","%s,w",
6761 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6762 pic16_emitcode("movwf","%s",
6763 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6765 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6766 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6767 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6772 if (AOP_TYPE(left) == AOP_ACC) {
6773 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6774 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6776 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6777 pic16_emitcode("andwf","%s,w",
6778 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6779 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6780 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6782 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6783 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6789 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6790 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6791 pic16_freeAsmop(result,NULL,ic,TRUE);
6794 /*-----------------------------------------------------------------*/
6795 /* genOr - code for or */
6796 /*-----------------------------------------------------------------*/
6797 static void genOr (iCode *ic, iCode *ifx)
6799 operand *left, *right, *result;
6801 unsigned long lit = 0L;
6803 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6805 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6806 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6807 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6809 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6811 /* if left is a literal & right is not then exchange them */
6812 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6813 AOP_NEEDSACC(left)) {
6814 operand *tmp = right ;
6819 /* if result = right then exchange them */
6820 if(pic16_sameRegs(AOP(result),AOP(right))){
6821 operand *tmp = right ;
6826 /* if right is bit then exchange them */
6827 if (AOP_TYPE(right) == AOP_CRY &&
6828 AOP_TYPE(left) != AOP_CRY){
6829 operand *tmp = right ;
6834 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6836 if(AOP_TYPE(right) == AOP_LIT)
6837 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6839 size = AOP_SIZE(result);
6843 if (AOP_TYPE(left) == AOP_CRY){
6844 if(AOP_TYPE(right) == AOP_LIT){
6845 // c = bit & literal;
6847 // lit != 0 => result = 1
6848 if(AOP_TYPE(result) == AOP_CRY){
6850 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6851 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6852 // AOP(result)->aopu.aop_dir,
6853 // AOP(result)->aopu.aop_dir);
6855 continueIfTrue(ifx);
6859 // lit == 0 => result = left
6860 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6862 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6865 if (AOP_TYPE(right) == AOP_CRY){
6866 if(pic16_sameRegs(AOP(result),AOP(left))){
6868 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6869 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6870 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6872 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6873 AOP(result)->aopu.aop_dir,
6874 AOP(result)->aopu.aop_dir);
6875 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6876 AOP(right)->aopu.aop_dir,
6877 AOP(right)->aopu.aop_dir);
6878 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6879 AOP(result)->aopu.aop_dir,
6880 AOP(result)->aopu.aop_dir);
6882 if( AOP_TYPE(result) == AOP_ACC) {
6883 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6884 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6885 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6886 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6890 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6891 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6892 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6893 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6895 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6896 AOP(result)->aopu.aop_dir,
6897 AOP(result)->aopu.aop_dir);
6898 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6899 AOP(right)->aopu.aop_dir,
6900 AOP(right)->aopu.aop_dir);
6901 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6902 AOP(left)->aopu.aop_dir,
6903 AOP(left)->aopu.aop_dir);
6904 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6905 AOP(result)->aopu.aop_dir,
6906 AOP(result)->aopu.aop_dir);
6911 symbol *tlbl = newiTempLabel(NULL);
6912 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6915 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6916 if( AOP_TYPE(right) == AOP_ACC) {
6917 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6919 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6920 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6925 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6926 pic16_emitcode(";XXX setb","c");
6927 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6928 AOP(left)->aopu.aop_dir,tlbl->key+100);
6929 pic16_toBoolean(right);
6930 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6931 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6932 jmpTrueOrFalse(ifx, tlbl);
6936 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6943 pic16_outBitC(result);
6945 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6946 genIfxJump(ifx, "c");
6950 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6951 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6952 if((AOP_TYPE(right) == AOP_LIT) &&
6953 (AOP_TYPE(result) == AOP_CRY) &&
6954 (AOP_TYPE(left) != AOP_CRY)){
6956 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6959 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6961 continueIfTrue(ifx);
6964 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6965 // lit = 0, result = boolean(left)
6967 pic16_emitcode(";XXX setb","c");
6968 pic16_toBoolean(right);
6970 symbol *tlbl = newiTempLabel(NULL);
6971 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6973 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6975 genIfxJump (ifx,"a");
6979 pic16_outBitC(result);
6983 /* if left is same as result */
6984 if(pic16_sameRegs(AOP(result),AOP(left))){
6986 for(;size--; offset++,lit>>=8) {
6987 if(AOP_TYPE(right) == AOP_LIT){
6988 if((lit & 0xff) == 0)
6989 /* or'ing with 0 has no effect */
6992 int p = my_powof2(lit & 0xff);
6994 /* only one bit is set in the literal, so use a bsf instruction */
6995 pic16_emitpcode(POC_BSF,
6996 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6998 if(know_W != (lit & 0xff))
6999 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7000 know_W = lit & 0xff;
7001 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7006 if (AOP_TYPE(left) == AOP_ACC) {
7007 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7008 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7010 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7011 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7013 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7014 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7020 // left & result in different registers
7021 if(AOP_TYPE(result) == AOP_CRY){
7023 // if(size), result in bit
7024 // if(!size && ifx), conditional oper: if(left | right)
7025 symbol *tlbl = newiTempLabel(NULL);
7026 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7027 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7031 pic16_emitcode(";XXX setb","c");
7033 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7034 pic16_emitcode(";XXX orl","a,%s",
7035 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7036 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7041 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7042 pic16_outBitC(result);
7044 jmpTrueOrFalse(ifx, tlbl);
7045 } else for(;(size--);offset++){
7047 // result = left & right
7048 if(AOP_TYPE(right) == AOP_LIT){
7049 int t = (lit >> (offset*8)) & 0x0FFL;
7052 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7053 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7055 pic16_emitcode("movf","%s,w",
7056 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7057 pic16_emitcode("movwf","%s",
7058 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7061 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7062 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7063 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7065 pic16_emitcode("movlw","0x%x",t);
7066 pic16_emitcode("iorwf","%s,w",
7067 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7068 pic16_emitcode("movwf","%s",
7069 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7075 // faster than result <- left, anl result,right
7076 // and better if result is SFR
7077 if (AOP_TYPE(left) == AOP_ACC) {
7078 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7079 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7081 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7082 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7084 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7085 pic16_emitcode("iorwf","%s,w",
7086 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7088 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7089 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7094 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7095 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7096 pic16_freeAsmop(result,NULL,ic,TRUE);
7099 /*-----------------------------------------------------------------*/
7100 /* genXor - code for xclusive or */
7101 /*-----------------------------------------------------------------*/
7102 static void genXor (iCode *ic, iCode *ifx)
7104 operand *left, *right, *result;
7106 unsigned long lit = 0L;
7108 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7110 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7111 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7112 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7114 /* if left is a literal & right is not ||
7115 if left needs acc & right does not */
7116 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7117 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7118 operand *tmp = right ;
7123 /* if result = right then exchange them */
7124 if(pic16_sameRegs(AOP(result),AOP(right))){
7125 operand *tmp = right ;
7130 /* if right is bit then exchange them */
7131 if (AOP_TYPE(right) == AOP_CRY &&
7132 AOP_TYPE(left) != AOP_CRY){
7133 operand *tmp = right ;
7137 if(AOP_TYPE(right) == AOP_LIT)
7138 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7140 size = AOP_SIZE(result);
7144 if (AOP_TYPE(left) == AOP_CRY){
7145 if(AOP_TYPE(right) == AOP_LIT){
7146 // c = bit & literal;
7148 // lit>>1 != 0 => result = 1
7149 if(AOP_TYPE(result) == AOP_CRY){
7151 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
7152 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7154 continueIfTrue(ifx);
7157 pic16_emitcode("setb","c");
7161 // lit == 0, result = left
7162 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7164 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7166 // lit == 1, result = not(left)
7167 if(size && pic16_sameRegs(AOP(result),AOP(left))){
7168 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
7169 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
7170 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7173 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7174 pic16_emitcode("cpl","c");
7181 symbol *tlbl = newiTempLabel(NULL);
7182 if (AOP_TYPE(right) == AOP_CRY){
7184 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7187 int sizer = AOP_SIZE(right);
7189 // if val>>1 != 0, result = 1
7190 pic16_emitcode("setb","c");
7192 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7194 // test the msb of the lsb
7195 pic16_emitcode("anl","a,#0xfe");
7196 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7200 pic16_emitcode("rrc","a");
7202 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7203 pic16_emitcode("cpl","c");
7204 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7209 pic16_outBitC(result);
7211 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7212 genIfxJump(ifx, "c");
7216 if(pic16_sameRegs(AOP(result),AOP(left))){
7217 /* if left is same as result */
7218 for(;size--; offset++) {
7219 if(AOP_TYPE(right) == AOP_LIT){
7220 int t = (lit >> (offset*8)) & 0x0FFL;
7224 if (IS_AOP_PREG(left)) {
7225 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7226 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7227 pic16_aopPut(AOP(result),"a",offset);
7229 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7230 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7231 pic16_emitcode("xrl","%s,%s",
7232 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7233 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7236 if (AOP_TYPE(left) == AOP_ACC)
7237 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7239 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7240 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7242 if (IS_AOP_PREG(left)) {
7243 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7244 pic16_aopPut(AOP(result),"a",offset);
7246 pic16_emitcode("xrl","%s,a",
7247 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7253 // left & result in different registers
7254 if(AOP_TYPE(result) == AOP_CRY){
7256 // if(size), result in bit
7257 // if(!size && ifx), conditional oper: if(left ^ right)
7258 symbol *tlbl = newiTempLabel(NULL);
7259 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7261 pic16_emitcode("setb","c");
7263 if((AOP_TYPE(right) == AOP_LIT) &&
7264 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7265 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7267 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7268 pic16_emitcode("xrl","a,%s",
7269 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7271 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7276 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7277 pic16_outBitC(result);
7279 jmpTrueOrFalse(ifx, tlbl);
7280 } else for(;(size--);offset++){
7282 // result = left & right
7283 if(AOP_TYPE(right) == AOP_LIT){
7284 int t = (lit >> (offset*8)) & 0x0FFL;
7287 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7288 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7289 pic16_emitcode("movf","%s,w",
7290 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7291 pic16_emitcode("movwf","%s",
7292 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7295 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7296 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7297 pic16_emitcode("comf","%s,w",
7298 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7299 pic16_emitcode("movwf","%s",
7300 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7303 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7304 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7305 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7306 pic16_emitcode("movlw","0x%x",t);
7307 pic16_emitcode("xorwf","%s,w",
7308 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7309 pic16_emitcode("movwf","%s",
7310 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7316 // faster than result <- left, anl result,right
7317 // and better if result is SFR
7318 if (AOP_TYPE(left) == AOP_ACC) {
7319 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7320 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7322 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7323 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7324 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7325 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7327 if ( AOP_TYPE(result) != AOP_ACC){
7328 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7329 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7335 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7336 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7337 pic16_freeAsmop(result,NULL,ic,TRUE);
7340 /*-----------------------------------------------------------------*/
7341 /* genInline - write the inline code out */
7342 /*-----------------------------------------------------------------*/
7343 static void genInline (iCode *ic)
7345 char *buffer, *bp, *bp1;
7347 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7349 _G.inLine += (!options.asmpeep);
7351 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7352 strcpy(buffer,IC_INLINE(ic));
7354 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7356 /* emit each line as a code */
7362 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7370 /* print label, use this special format with NULL directive
7371 * to denote that the argument should not be indented with tab */
7372 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7379 if ((bp1 != bp) && *bp1)
7380 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7385 _G.inLine -= (!options.asmpeep);
7388 /*-----------------------------------------------------------------*/
7389 /* genRRC - rotate right with carry */
7390 /*-----------------------------------------------------------------*/
7391 static void genRRC (iCode *ic)
7393 operand *left , *result ;
7394 int size, offset = 0, same;
7396 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7398 /* rotate right with carry */
7400 result=IC_RESULT(ic);
7401 pic16_aopOp (left,ic,FALSE);
7402 pic16_aopOp (result,ic,FALSE);
7404 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7406 same = pic16_sameRegs(AOP(result),AOP(left));
7408 size = AOP_SIZE(result);
7410 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7412 /* get the lsb and put it into the carry */
7413 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7420 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7422 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7423 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7429 pic16_freeAsmop(left,NULL,ic,TRUE);
7430 pic16_freeAsmop(result,NULL,ic,TRUE);
7433 /*-----------------------------------------------------------------*/
7434 /* genRLC - generate code for rotate left with carry */
7435 /*-----------------------------------------------------------------*/
7436 static void genRLC (iCode *ic)
7438 operand *left , *result ;
7439 int size, offset = 0;
7442 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7443 /* rotate right with carry */
7445 result=IC_RESULT(ic);
7446 pic16_aopOp (left,ic,FALSE);
7447 pic16_aopOp (result,ic,FALSE);
7449 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7451 same = pic16_sameRegs(AOP(result),AOP(left));
7453 /* move it to the result */
7454 size = AOP_SIZE(result);
7456 /* get the msb and put it into the carry */
7457 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7464 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7466 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7467 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7474 pic16_freeAsmop(left,NULL,ic,TRUE);
7475 pic16_freeAsmop(result,NULL,ic,TRUE);
7479 /* gpasm can get the highest order bit with HIGH/UPPER
7480 * so the following probably is not needed -- VR */
7482 /*-----------------------------------------------------------------*/
7483 /* genGetHbit - generates code get highest order bit */
7484 /*-----------------------------------------------------------------*/
7485 static void genGetHbit (iCode *ic)
7487 operand *left, *result;
7489 result=IC_RESULT(ic);
7490 pic16_aopOp (left,ic,FALSE);
7491 pic16_aopOp (result,ic,FALSE);
7493 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7494 /* get the highest order byte into a */
7495 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7496 if(AOP_TYPE(result) == AOP_CRY){
7497 pic16_emitcode("rlc","a");
7498 pic16_outBitC(result);
7501 pic16_emitcode("rl","a");
7502 pic16_emitcode("anl","a,#0x01");
7503 pic16_outAcc(result);
7507 pic16_freeAsmop(left,NULL,ic,TRUE);
7508 pic16_freeAsmop(result,NULL,ic,TRUE);
7512 /*-----------------------------------------------------------------*/
7513 /* AccRol - rotate left accumulator by known count */
7514 /*-----------------------------------------------------------------*/
7515 static void AccRol (int shCount)
7517 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7518 shCount &= 0x0007; // shCount : 0..7
7523 pic16_emitcode("rl","a");
7526 pic16_emitcode("rl","a");
7527 pic16_emitcode("rl","a");
7530 pic16_emitcode("swap","a");
7531 pic16_emitcode("rr","a");
7534 pic16_emitcode("swap","a");
7537 pic16_emitcode("swap","a");
7538 pic16_emitcode("rl","a");
7541 pic16_emitcode("rr","a");
7542 pic16_emitcode("rr","a");
7545 pic16_emitcode("rr","a");
7551 /*-----------------------------------------------------------------*/
7552 /* AccLsh - left shift accumulator by known count */
7553 /*-----------------------------------------------------------------*/
7554 static void AccLsh (int shCount)
7556 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7562 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7565 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7566 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7569 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7570 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7573 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7576 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7577 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7580 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7581 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7584 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7588 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7591 /*-----------------------------------------------------------------*/
7592 /* AccRsh - right shift accumulator by known count */
7593 /*-----------------------------------------------------------------*/
7594 static void AccRsh (int shCount, int andmask)
7596 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7601 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7602 // andmask = 0; /* no need */
7605 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7606 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7607 // andmask = 0; /* no need */
7610 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7611 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7614 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7617 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7618 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7621 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7622 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7625 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7630 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7632 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7636 /*-----------------------------------------------------------------*/
7637 /* AccSRsh - signed right shift accumulator by known count */
7638 /*-----------------------------------------------------------------*/
7639 static void AccSRsh (int shCount)
7642 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7645 pic16_emitcode("mov","c,acc.7");
7646 pic16_emitcode("rrc","a");
7647 } else if(shCount == 2){
7648 pic16_emitcode("mov","c,acc.7");
7649 pic16_emitcode("rrc","a");
7650 pic16_emitcode("mov","c,acc.7");
7651 pic16_emitcode("rrc","a");
7653 tlbl = newiTempLabel(NULL);
7654 /* rotate right accumulator */
7655 AccRol(8 - shCount);
7656 /* and kill the higher order bits */
7657 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7658 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7659 pic16_emitcode("orl","a,#0x%02x",
7660 (unsigned char)~SRMask[shCount]);
7661 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7666 /*-----------------------------------------------------------------*/
7667 /* shiftR1Left2Result - shift right one byte from left to result */
7668 /*-----------------------------------------------------------------*/
7669 static void shiftR1Left2ResultSigned (operand *left, int offl,
7670 operand *result, int offr,
7675 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7677 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7681 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7683 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7685 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7686 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7692 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7694 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7696 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7697 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7699 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7700 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7706 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7708 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7709 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7712 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7713 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7714 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7716 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7717 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7719 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7723 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7724 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7725 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7726 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
7727 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7731 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7733 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7734 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7736 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7737 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
7738 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7739 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
7740 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7745 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7746 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7747 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7748 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7749 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7750 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7752 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7753 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7754 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7755 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7756 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7762 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7763 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7764 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7765 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7767 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7768 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7769 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7777 /*-----------------------------------------------------------------*/
7778 /* shiftR1Left2Result - shift right one byte from left to result */
7779 /*-----------------------------------------------------------------*/
7780 static void shiftR1Left2Result (operand *left, int offl,
7781 operand *result, int offr,
7782 int shCount, int sign)
7786 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7788 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7790 /* Copy the msb into the carry if signed. */
7792 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7802 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7804 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7805 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7811 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7813 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7814 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7817 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7822 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7824 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7825 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7828 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7829 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7830 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7831 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7835 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7836 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7837 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7841 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7842 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7843 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7845 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7850 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7851 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7852 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7853 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7854 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7859 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7860 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7861 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7870 /*-----------------------------------------------------------------*/
7871 /* shiftL1Left2Result - shift left one byte from left to result */
7872 /*-----------------------------------------------------------------*/
7873 static void shiftL1Left2Result (operand *left, int offl,
7874 operand *result, int offr, int shCount)
7879 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7881 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7882 DEBUGpic16_emitcode ("; ***","same = %d",same);
7883 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7885 /* shift left accumulator */
7886 //AccLsh(shCount); // don't comment out just yet...
7887 // pic16_aopPut(AOP(result),"a",offr);
7891 /* Shift left 1 bit position */
7892 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7894 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7896 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7897 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7901 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7902 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7903 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7904 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7907 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7908 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7909 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7910 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7911 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7914 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7915 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7916 pic16_emitpcode(POC_MOVWF,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));
7922 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7925 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7926 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7927 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7928 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7929 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7932 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7933 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7934 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7938 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7943 /*-----------------------------------------------------------------*/
7944 /* movLeft2Result - move byte from left to result */
7945 /*-----------------------------------------------------------------*/
7946 static void movLeft2Result (operand *left, int offl,
7947 operand *result, int offr)
7950 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7951 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7952 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7954 if (*l == '@' && (IS_AOP_PREG(result))) {
7955 pic16_emitcode("mov","a,%s",l);
7956 pic16_aopPut(AOP(result),"a",offr);
7958 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7959 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7964 /*-----------------------------------------------------------------*/
7965 /* shiftL2Left2Result - shift left two bytes from left to result */
7966 /*-----------------------------------------------------------------*/
7967 static void shiftL2Left2Result (operand *left, int offl,
7968 operand *result, int offr, int shCount)
7970 int same = pic16_sameRegs(AOP(result), AOP(left));
7973 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7975 if (same && (offl != offr)) { // shift bytes
7978 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7979 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7981 } else { // just treat as different later on
7994 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7995 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7996 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8000 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8001 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8007 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8008 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8009 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8010 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8011 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8012 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8013 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8015 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8016 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8020 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8021 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8022 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8023 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8024 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8025 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8026 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8027 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8028 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8029 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8032 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8033 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8034 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8035 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8036 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8046 /* note, use a mov/add for the shift since the mov has a
8047 chance of getting optimized out */
8048 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8049 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8050 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8051 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8052 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8056 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8057 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8063 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8064 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8065 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8066 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8067 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8068 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8069 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8070 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8074 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8075 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8079 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8080 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8081 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8082 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8084 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8085 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8086 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8087 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8088 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8089 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8090 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8091 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8094 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8095 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8096 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8097 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8098 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8103 /*-----------------------------------------------------------------*/
8104 /* shiftR2Left2Result - shift right two bytes from left to result */
8105 /*-----------------------------------------------------------------*/
8106 static void shiftR2Left2Result (operand *left, int offl,
8107 operand *result, int offr,
8108 int shCount, int sign)
8110 int same = pic16_sameRegs(AOP(result), AOP(left));
8112 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8114 if (same && (offl != offr)) { // shift right bytes
8117 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8118 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8120 } else { // just treat as different later on
8132 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8137 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8138 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8140 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8141 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8142 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8143 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8148 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8151 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8152 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8159 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
8160 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
8161 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8163 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8164 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
8165 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8166 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8168 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8169 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8170 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8172 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8173 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8174 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8175 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8176 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8180 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8181 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8185 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
8186 pic16_emitpcode(POC_BTFSC,
8187 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
8188 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8196 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8197 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8199 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8200 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8201 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8202 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8204 pic16_emitpcode(POC_BTFSC,
8205 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8206 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8208 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8209 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8210 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8211 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8213 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8214 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8215 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8216 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8217 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8218 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8219 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8220 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8222 pic16_emitpcode(POC_BTFSC,
8223 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8224 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8226 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8227 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8234 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8235 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8236 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8237 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8240 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8242 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8247 /*-----------------------------------------------------------------*/
8248 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8249 /*-----------------------------------------------------------------*/
8250 static void shiftLLeftOrResult (operand *left, int offl,
8251 operand *result, int offr, int shCount)
8253 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8255 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8256 /* shift left accumulator */
8258 /* or with result */
8259 /* back to result */
8260 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8263 /*-----------------------------------------------------------------*/
8264 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8265 /*-----------------------------------------------------------------*/
8266 static void shiftRLeftOrResult (operand *left, int offl,
8267 operand *result, int offr, int shCount)
8269 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8271 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8272 /* shift right accumulator */
8274 /* or with result */
8275 /* back to result */
8276 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8279 /*-----------------------------------------------------------------*/
8280 /* genlshOne - left shift a one byte quantity by known count */
8281 /*-----------------------------------------------------------------*/
8282 static void genlshOne (operand *result, operand *left, int shCount)
8284 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8285 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8288 /*-----------------------------------------------------------------*/
8289 /* genlshTwo - left shift two bytes by known amount != 0 */
8290 /*-----------------------------------------------------------------*/
8291 static void genlshTwo (operand *result,operand *left, int shCount)
8295 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8296 size = pic16_getDataSize(result);
8298 /* if shCount >= 8 */
8304 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8306 movLeft2Result(left, LSB, result, MSB16);
8308 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8311 /* 1 <= shCount <= 7 */
8314 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8316 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8320 /*-----------------------------------------------------------------*/
8321 /* shiftLLong - shift left one long from left to result */
8322 /* offr = LSB or MSB16 */
8323 /*-----------------------------------------------------------------*/
8324 static void shiftLLong (operand *left, operand *result, int offr )
8326 int size = AOP_SIZE(result);
8327 int same = pic16_sameRegs(AOP(left),AOP(result));
8330 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8332 if (same && (offr == MSB16)) { //shift one byte
8333 for(i=size-1;i>=MSB16;i--) {
8334 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8335 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8338 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8341 if (size >= LSB+offr ){
8343 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8345 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8346 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8350 if(size >= MSB16+offr){
8352 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8354 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8355 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8359 if(size >= MSB24+offr){
8361 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8363 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8364 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8368 if(size > MSB32+offr){
8370 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8372 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8373 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8377 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8381 /*-----------------------------------------------------------------*/
8382 /* genlshFour - shift four byte by a known amount != 0 */
8383 /*-----------------------------------------------------------------*/
8384 static void genlshFour (operand *result, operand *left, int shCount)
8388 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8389 size = AOP_SIZE(result);
8391 /* if shifting more that 3 bytes */
8392 if (shCount >= 24 ) {
8395 /* lowest order of left goes to the highest
8396 order of the destination */
8397 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8399 movLeft2Result(left, LSB, result, MSB32);
8401 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8402 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8403 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8408 /* more than two bytes */
8409 else if ( shCount >= 16 ) {
8410 /* lower order two bytes goes to higher order two bytes */
8412 /* if some more remaining */
8414 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8416 movLeft2Result(left, MSB16, result, MSB32);
8417 movLeft2Result(left, LSB, result, MSB24);
8419 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8420 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8424 /* if more than 1 byte */
8425 else if ( shCount >= 8 ) {
8426 /* lower order three bytes goes to higher order three bytes */
8430 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8432 movLeft2Result(left, LSB, result, MSB16);
8434 else{ /* size = 4 */
8436 movLeft2Result(left, MSB24, result, MSB32);
8437 movLeft2Result(left, MSB16, result, MSB24);
8438 movLeft2Result(left, LSB, result, MSB16);
8439 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8441 else if(shCount == 1)
8442 shiftLLong(left, result, MSB16);
8444 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8445 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8446 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8447 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8452 /* 1 <= shCount <= 7 */
8453 else if(shCount <= 3)
8455 shiftLLong(left, result, LSB);
8456 while(--shCount >= 1)
8457 shiftLLong(result, result, LSB);
8459 /* 3 <= shCount <= 7, optimize */
8461 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8462 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8463 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8467 /*-----------------------------------------------------------------*/
8468 /* genLeftShiftLiteral - left shifting by known count */
8469 /*-----------------------------------------------------------------*/
8470 static void genLeftShiftLiteral (operand *left,
8475 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8478 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8479 pic16_freeAsmop(right,NULL,ic,TRUE);
8481 pic16_aopOp(left,ic,FALSE);
8482 pic16_aopOp(result,ic,FALSE);
8484 size = getSize(operandType(result));
8487 pic16_emitcode("; shift left ","result %d, left %d",size,
8491 /* I suppose that the left size >= result size */
8494 movLeft2Result(left, size, result, size);
8498 else if(shCount >= (size * 8))
8500 pic16_aopPut(AOP(result),zero,size);
8504 genlshOne (result,left,shCount);
8509 genlshTwo (result,left,shCount);
8513 genlshFour (result,left,shCount);
8517 pic16_freeAsmop(left,NULL,ic,TRUE);
8518 pic16_freeAsmop(result,NULL,ic,TRUE);
8521 /*-----------------------------------------------------------------*
8522 * genMultiAsm - repeat assembly instruction for size of register.
8523 * if endian == 1, then the high byte (i.e base address + size of
8524 * register) is used first else the low byte is used first;
8525 *-----------------------------------------------------------------*/
8526 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8531 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8544 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
8549 /*-----------------------------------------------------------------*/
8550 /* genLeftShift - generates code for left shifting */
8551 /*-----------------------------------------------------------------*/
8552 static void genLeftShift (iCode *ic)
8554 operand *left,*right, *result;
8557 symbol *tlbl , *tlbl1;
8560 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8562 right = IC_RIGHT(ic);
8564 result = IC_RESULT(ic);
8566 pic16_aopOp(right,ic,FALSE);
8568 /* if the shift count is known then do it
8569 as efficiently as possible */
8570 if (AOP_TYPE(right) == AOP_LIT) {
8571 genLeftShiftLiteral (left,right,result,ic);
8575 /* shift count is unknown then we have to form
8576 a loop get the loop count in B : Note: we take
8577 only the lower order byte since shifting
8578 more that 32 bits make no sense anyway, ( the
8579 largest size of an object can be only 32 bits ) */
8582 pic16_aopOp(left,ic,FALSE);
8583 pic16_aopOp(result,ic,FALSE);
8585 /* now move the left to the result if they are not the
8587 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8588 AOP_SIZE(result) > 1) {
8590 size = AOP_SIZE(result);
8593 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8594 if (*l == '@' && (IS_AOP_PREG(result))) {
8596 pic16_emitcode("mov","a,%s",l);
8597 pic16_aopPut(AOP(result),"a",offset);
8599 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8600 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8601 //pic16_aopPut(AOP(result),l,offset);
8607 size = AOP_SIZE(result);
8609 /* if it is only one byte then */
8611 if(optimized_for_speed) {
8612 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8613 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8614 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8615 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8616 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8617 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8618 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8619 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
8620 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
8621 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
8622 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8623 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8626 tlbl = newiTempLabel(NULL);
8627 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8628 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8629 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8632 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8633 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8634 pic16_emitpLabel(tlbl->key);
8635 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8636 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8638 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8643 if (pic16_sameRegs(AOP(left),AOP(result))) {
8645 tlbl = newiTempLabel(NULL);
8646 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8647 genMultiAsm(POC_RRCF, result, size,1);
8648 pic16_emitpLabel(tlbl->key);
8649 genMultiAsm(POC_RLCF, result, size,0);
8650 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8652 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8656 //tlbl = newiTempLabel(NULL);
8658 //tlbl1 = newiTempLabel(NULL);
8660 //reAdjustPreg(AOP(result));
8662 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8663 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8664 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8666 //pic16_emitcode("add","a,acc");
8667 //pic16_aopPut(AOP(result),"a",offset++);
8669 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8671 // pic16_emitcode("rlc","a");
8672 // pic16_aopPut(AOP(result),"a",offset++);
8674 //reAdjustPreg(AOP(result));
8676 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8677 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8680 tlbl = newiTempLabel(NULL);
8681 tlbl1= newiTempLabel(NULL);
8683 size = AOP_SIZE(result);
8686 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8688 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8690 /* offset should be 0, 1 or 3 */
8692 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8694 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8696 pic16_emitpcode(POC_MOVWF, pctemp);
8699 pic16_emitpLabel(tlbl->key);
8702 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8704 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
8706 pic16_emitpcode(POC_DECFSZ, pctemp);
8707 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8708 pic16_emitpLabel(tlbl1->key);
8710 pic16_popReleaseTempReg(pctemp);
8714 pic16_freeAsmop (right,NULL,ic,TRUE);
8715 pic16_freeAsmop(left,NULL,ic,TRUE);
8716 pic16_freeAsmop(result,NULL,ic,TRUE);
8719 /*-----------------------------------------------------------------*/
8720 /* genrshOne - right shift a one byte quantity by known count */
8721 /*-----------------------------------------------------------------*/
8722 static void genrshOne (operand *result, operand *left,
8723 int shCount, int sign)
8725 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8726 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8729 /*-----------------------------------------------------------------*/
8730 /* genrshTwo - right shift two bytes by known amount != 0 */
8731 /*-----------------------------------------------------------------*/
8732 static void genrshTwo (operand *result,operand *left,
8733 int shCount, int sign)
8735 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8736 /* if shCount >= 8 */
8740 shiftR1Left2Result(left, MSB16, result, LSB,
8743 movLeft2Result(left, MSB16, result, LSB);
8745 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8748 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8749 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8753 /* 1 <= shCount <= 7 */
8755 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
8758 /*-----------------------------------------------------------------*/
8759 /* shiftRLong - shift right one long from left to result */
8760 /* offl = LSB or MSB16 */
8761 /*-----------------------------------------------------------------*/
8762 static void shiftRLong (operand *left, int offl,
8763 operand *result, int sign)
8765 int size = AOP_SIZE(result);
8766 int same = pic16_sameRegs(AOP(left),AOP(result));
8768 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8770 if (same && (offl == MSB16)) { //shift one byte right
8771 for(i=MSB16;i<size;i++) {
8772 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8773 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8778 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8784 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8786 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8787 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8791 /* add sign of "a" */
8792 pic16_addSign(result, MSB32, sign);
8796 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8798 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8799 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8803 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8805 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8806 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8810 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8813 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8814 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8819 /*-----------------------------------------------------------------*/
8820 /* genrshFour - shift four byte by a known amount != 0 */
8821 /*-----------------------------------------------------------------*/
8822 static void genrshFour (operand *result, operand *left,
8823 int shCount, int sign)
8825 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8826 /* if shifting more that 3 bytes */
8827 if(shCount >= 24 ) {
8830 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8832 movLeft2Result(left, MSB32, result, LSB);
8834 pic16_addSign(result, MSB16, sign);
8836 else if(shCount >= 16){
8839 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8841 movLeft2Result(left, MSB24, result, LSB);
8842 movLeft2Result(left, MSB32, result, MSB16);
8844 pic16_addSign(result, MSB24, sign);
8846 else if(shCount >= 8){
8849 shiftRLong(left, MSB16, result, sign);
8850 else if(shCount == 0){
8851 movLeft2Result(left, MSB16, result, LSB);
8852 movLeft2Result(left, MSB24, result, MSB16);
8853 movLeft2Result(left, MSB32, result, MSB24);
8854 pic16_addSign(result, MSB32, sign);
8856 else{ //shcount >= 2
8857 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8858 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8859 /* the last shift is signed */
8860 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8861 pic16_addSign(result, MSB32, sign);
8864 else{ /* 1 <= shCount <= 7 */
8866 shiftRLong(left, LSB, result, sign);
8868 shiftRLong(result, LSB, result, sign);
8871 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8872 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8873 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8878 /*-----------------------------------------------------------------*/
8879 /* genRightShiftLiteral - right shifting by known count */
8880 /*-----------------------------------------------------------------*/
8881 static void genRightShiftLiteral (operand *left,
8887 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8890 pic16_freeAsmop(right,NULL,ic,TRUE);
8892 pic16_aopOp(left,ic,FALSE);
8893 pic16_aopOp(result,ic,FALSE);
8895 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8898 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8902 lsize = pic16_getDataSize(left);
8903 res_size = pic16_getDataSize(result);
8904 /* test the LEFT size !!! */
8906 /* I suppose that the left size >= result size */
8909 movLeft2Result(left, lsize, result, res_size);
8912 else if(shCount >= (lsize * 8)){
8915 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8917 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8918 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8923 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8924 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8925 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8927 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8932 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8939 genrshOne (result,left,shCount,sign);
8943 genrshTwo (result,left,shCount,sign);
8947 genrshFour (result,left,shCount,sign);
8955 pic16_freeAsmop(left,NULL,ic,TRUE);
8956 pic16_freeAsmop(result,NULL,ic,TRUE);
8959 /*-----------------------------------------------------------------*/
8960 /* genSignedRightShift - right shift of signed number */
8961 /*-----------------------------------------------------------------*/
8962 static void genSignedRightShift (iCode *ic)
8964 operand *right, *left, *result;
8967 symbol *tlbl, *tlbl1 ;
8970 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8972 /* we do it the hard way put the shift count in b
8973 and loop thru preserving the sign */
8974 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8976 right = IC_RIGHT(ic);
8978 result = IC_RESULT(ic);
8980 pic16_aopOp(right,ic,FALSE);
8981 pic16_aopOp(left,ic,FALSE);
8982 pic16_aopOp(result,ic,FALSE);
8985 if ( AOP_TYPE(right) == AOP_LIT) {
8986 genRightShiftLiteral (left,right,result,ic,1);
8989 /* shift count is unknown then we have to form
8990 a loop get the loop count in B : Note: we take
8991 only the lower order byte since shifting
8992 more that 32 bits make no sense anyway, ( the
8993 largest size of an object can be only 32 bits ) */
8995 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8996 //pic16_emitcode("inc","b");
8997 //pic16_freeAsmop (right,NULL,ic,TRUE);
8998 //pic16_aopOp(left,ic,FALSE);
8999 //pic16_aopOp(result,ic,FALSE);
9001 /* now move the left to the result if they are not the
9003 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9004 AOP_SIZE(result) > 1) {
9006 size = AOP_SIZE(result);
9010 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9011 if (*l == '@' && IS_AOP_PREG(result)) {
9013 pic16_emitcode("mov","a,%s",l);
9014 pic16_aopPut(AOP(result),"a",offset);
9016 pic16_aopPut(AOP(result),l,offset);
9018 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
9019 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9025 /* mov the highest order bit to OVR */
9026 tlbl = newiTempLabel(NULL);
9027 tlbl1= newiTempLabel(NULL);
9029 size = AOP_SIZE(result);
9032 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
9034 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9036 /* offset should be 0, 1 or 3 */
9037 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
9039 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9041 pic16_emitpcode(POC_MOVWF, pctemp);
9044 pic16_emitpLabel(tlbl->key);
9046 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
9047 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
9050 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
9053 pic16_emitpcode(POC_DECFSZ, pctemp);
9054 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9055 pic16_emitpLabel(tlbl1->key);
9057 pic16_popReleaseTempReg(pctemp);
9059 size = AOP_SIZE(result);
9061 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
9062 pic16_emitcode("rlc","a");
9063 pic16_emitcode("mov","ov,c");
9064 /* if it is only one byte then */
9066 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9068 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9069 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9070 pic16_emitcode("mov","c,ov");
9071 pic16_emitcode("rrc","a");
9072 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9073 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9074 pic16_aopPut(AOP(result),"a",0);
9078 reAdjustPreg(AOP(result));
9079 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9080 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9081 pic16_emitcode("mov","c,ov");
9083 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9085 pic16_emitcode("rrc","a");
9086 pic16_aopPut(AOP(result),"a",offset--);
9088 reAdjustPreg(AOP(result));
9089 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9090 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9095 pic16_freeAsmop(left,NULL,ic,TRUE);
9096 pic16_freeAsmop(result,NULL,ic,TRUE);
9097 pic16_freeAsmop(right,NULL,ic,TRUE);
9100 /*-----------------------------------------------------------------*/
9101 /* genRightShift - generate code for right shifting */
9102 /*-----------------------------------------------------------------*/
9103 static void genRightShift (iCode *ic)
9105 operand *right, *left, *result;
9109 symbol *tlbl, *tlbl1 ;
9111 /* if signed then we do it the hard way preserve the
9112 sign bit moving it inwards */
9113 letype = getSpec(operandType(IC_LEFT(ic)));
9114 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9116 if (!SPEC_USIGN(letype)) {
9117 genSignedRightShift (ic);
9121 /* signed & unsigned types are treated the same : i.e. the
9122 signed is NOT propagated inwards : quoting from the
9123 ANSI - standard : "for E1 >> E2, is equivalent to division
9124 by 2**E2 if unsigned or if it has a non-negative value,
9125 otherwise the result is implementation defined ", MY definition
9126 is that the sign does not get propagated */
9128 right = IC_RIGHT(ic);
9130 result = IC_RESULT(ic);
9132 pic16_aopOp(right,ic,FALSE);
9134 /* if the shift count is known then do it
9135 as efficiently as possible */
9136 if (AOP_TYPE(right) == AOP_LIT) {
9137 genRightShiftLiteral (left,right,result,ic, 0);
9141 /* shift count is unknown then we have to form
9142 a loop get the loop count in B : Note: we take
9143 only the lower order byte since shifting
9144 more that 32 bits make no sense anyway, ( the
9145 largest size of an object can be only 32 bits ) */
9147 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9148 pic16_emitcode("inc","b");
9149 pic16_aopOp(left,ic,FALSE);
9150 pic16_aopOp(result,ic,FALSE);
9152 /* now move the left to the result if they are not the
9154 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9155 AOP_SIZE(result) > 1) {
9157 size = AOP_SIZE(result);
9160 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9161 if (*l == '@' && IS_AOP_PREG(result)) {
9163 pic16_emitcode("mov","a,%s",l);
9164 pic16_aopPut(AOP(result),"a",offset);
9166 pic16_aopPut(AOP(result),l,offset);
9171 tlbl = newiTempLabel(NULL);
9172 tlbl1= newiTempLabel(NULL);
9173 size = AOP_SIZE(result);
9176 /* if it is only one byte then */
9179 tlbl = newiTempLabel(NULL);
9180 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9181 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9182 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9185 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9186 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9187 pic16_emitpLabel(tlbl->key);
9188 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9189 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9191 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9196 reAdjustPreg(AOP(result));
9197 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9198 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9201 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9203 pic16_emitcode("rrc","a");
9204 pic16_aopPut(AOP(result),"a",offset--);
9206 reAdjustPreg(AOP(result));
9208 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9209 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9212 pic16_freeAsmop(left,NULL,ic,TRUE);
9213 pic16_freeAsmop (right,NULL,ic,TRUE);
9214 pic16_freeAsmop(result,NULL,ic,TRUE);
9218 void pic16_loadFSR0(operand *op)
9220 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9223 /*-----------------------------------------------------------------*/
9224 /* genUnpackBits - generates code for unpacking bits */
9225 /*-----------------------------------------------------------------*/
9226 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
9233 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9234 etype = getSpec(operandType(result));
9236 /* the following call to pic16_loadFSR0 is temporary until
9237 * optimization to handle single bit assignments is added
9238 * to the function. Until then use the old safe way! -- VR */
9239 pic16_loadFSR0( left );
9241 /* read the first byte */
9248 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9251 pic16_emitcode("clr","a");
9252 pic16_emitcode("movc","a","@a+dptr");
9257 /* if we have bitdisplacement then it fits */
9258 /* into this byte completely or if length is */
9259 /* less than a byte */
9260 if ((shCnt = SPEC_BSTR(etype)) ||
9261 (SPEC_BLEN(etype) <= 8)) {
9263 /* shift right acc */
9266 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9267 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9269 /* VR -- normally I would use the following, but since we use the hack,
9270 * to avoid the masking from AccRsh, why not mask it right now? */
9273 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9276 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9282 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9283 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9286 /* bit field did not fit in a byte */
9287 rlen = SPEC_BLEN(etype) - 8;
9288 pic16_aopPut(AOP(result),"a",offset++);
9295 pic16_emitcode("inc","%s",rname);
9296 pic16_emitcode("mov","a,@%s",rname);
9300 pic16_emitcode("inc","%s",rname);
9301 pic16_emitcode("movx","a,@%s",rname);
9305 pic16_emitcode("inc","dptr");
9306 pic16_emitcode("movx","a,@dptr");
9310 pic16_emitcode("clr","a");
9311 pic16_emitcode("inc","dptr");
9312 pic16_emitcode("movc","a","@a+dptr");
9316 pic16_emitcode("inc","dptr");
9317 pic16_emitcode("lcall","__gptrget");
9322 /* if we are done */
9326 pic16_aopPut(AOP(result),"a",offset++);
9331 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9332 pic16_aopPut(AOP(result),"a",offset);
9339 static void genDataPointerGet(operand *left,
9343 int size, offset = 0, leoffset=0 ;
9345 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9346 pic16_aopOp(result, ic, FALSE);
9348 size = AOP_SIZE(result);
9349 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9353 /* The following tests may save a redudant movff instruction when
9354 * accessing unions */
9356 /* if they are the same */
9357 if (operandsEqu (left, result)) {
9358 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9364 /* if they are the same registers */
9365 if (pic16_sameRegs(AOP(left),AOP(result))) {
9366 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9372 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9373 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9374 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9381 if ( AOP_TYPE(left) == AOP_PCODE) {
9382 fprintf(stderr,"genDataPointerGet %s, %d\n",
9383 AOP(left)->aopu.pcop->name,
9384 (AOP(left)->aopu.pcop->type == PO_DIR)?
9385 PCOR(AOP(left)->aopu.pcop)->instance:
9386 PCOI(AOP(left)->aopu.pcop)->offset);
9390 if(AOP(left)->aopu.pcop->type == PO_DIR)
9391 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9393 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9396 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9398 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9399 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9400 mov2w(AOP(left), offset); // patch 8
9401 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9403 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9404 pic16_popGet(AOP(left), offset), //patch 8
9405 pic16_popGet(AOP(result), offset)));
9413 pic16_freeAsmop(result,NULL,ic,TRUE);
9418 /*-----------------------------------------------------------------*/
9419 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
9420 /*-----------------------------------------------------------------*/
9421 static void genNearPointerGet (operand *left,
9426 //regs *preg = NULL ;
9427 sym_link *rtype, *retype;
9428 sym_link *ltype = operandType(left);
9430 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9431 rtype = operandType(result);
9432 retype= getSpec(rtype);
9434 pic16_aopOp(left,ic,FALSE);
9436 // pic16_DumpOp("(left)",left);
9437 // pic16_DumpOp("(result)",result);
9439 /* if left is rematerialisable and
9440 * result is not bit variable type and
9441 * the left is pointer to data space i.e
9442 * lower 128 bytes of space */
9443 if (AOP_TYPE(left) == AOP_PCODE
9444 && !IS_BITFIELD(retype)
9445 && DCL_TYPE(ltype) == POINTER) {
9447 genDataPointerGet (left,result,ic);
9448 pic16_freeAsmop(left, NULL, ic, TRUE);
9452 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9454 /* if the value is already in a pointer register
9455 * then don't need anything more */
9456 if (!AOP_INPREG(AOP(left))) {
9457 /* otherwise get a free pointer register */
9458 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9460 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9461 if( (AOP_TYPE(left) == AOP_PCODE)
9462 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9463 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9465 if(!IS_BITFIELD(retype))
9466 pic16_loadFSR0( left ); // patch 10
9468 // set up FSR0 with address from left
9469 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9470 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9474 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9476 pic16_aopOp (result,ic,FALSE);
9478 /* if bitfield then unpack the bits */
9479 if (IS_BITFIELD(retype))
9480 genUnpackBits (result, left, NULL, POINTER);
9482 /* we have can just get the values */
9483 int size = AOP_SIZE(result);
9486 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9489 /* fsr0 is loaded already -- VR */
9490 // pic16_loadFSR0( left );
9492 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9493 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9497 pic16_emitpcode(POC_MOVFF,
9498 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9499 pic16_popGet(AOP(result), offset++)));
9501 pic16_emitpcode(POC_MOVFF,
9502 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9503 pic16_popGet(AOP(result), offset++)));
9507 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9508 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9510 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9514 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9516 pic16_emitcode("mov","a,@%s",rname);
9517 pic16_aopPut(AOP(result),"a",offset);
9519 sprintf(buffer,"@%s",rname);
9520 pic16_aopPut(AOP(result),buffer,offset);
9524 pic16_emitcode("inc","%s",rname);
9529 /* now some housekeeping stuff */
9531 /* we had to allocate for this iCode */
9532 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9533 pic16_freeAsmop(NULL,aop,ic,TRUE);
9535 /* we did not allocate which means left
9536 already in a pointer register, then
9537 if size > 0 && this could be used again
9538 we have to point it back to where it
9540 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9541 if (AOP_SIZE(result) > 1 &&
9542 !OP_SYMBOL(left)->remat &&
9543 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9545 // int size = AOP_SIZE(result) - 1;
9547 // pic16_emitcode("dec","%s",rname);
9552 pic16_freeAsmop(left,NULL,ic,TRUE);
9553 pic16_freeAsmop(result,NULL,ic,TRUE);
9557 /*-----------------------------------------------------------------*/
9558 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
9559 /*-----------------------------------------------------------------*/
9560 static void genPagedPointerGet (operand *left,
9567 sym_link *rtype, *retype;
9569 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9571 rtype = operandType(result);
9572 retype= getSpec(rtype);
9574 pic16_aopOp(left,ic,FALSE);
9576 /* if the value is already in a pointer register
9577 then don't need anything more */
9578 if (!AOP_INPREG(AOP(left))) {
9579 /* otherwise get a free pointer register */
9581 preg = getFreePtr(ic,&aop,FALSE);
9582 pic16_emitcode("mov","%s,%s",
9584 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9585 rname = preg->name ;
9587 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9589 pic16_freeAsmop(left,NULL,ic,TRUE);
9590 pic16_aopOp (result,ic,FALSE);
9592 /* if bitfield then unpack the bits */
9593 if (IS_BITFIELD(retype))
9594 genUnpackBits (result,left,rname,PPOINTER);
9596 /* we have can just get the values */
9597 int size = AOP_SIZE(result);
9602 pic16_emitcode("movx","a,@%s",rname);
9603 pic16_aopPut(AOP(result),"a",offset);
9608 pic16_emitcode("inc","%s",rname);
9612 /* now some housekeeping stuff */
9614 /* we had to allocate for this iCode */
9615 pic16_freeAsmop(NULL,aop,ic,TRUE);
9617 /* we did not allocate which means left
9618 already in a pointer register, then
9619 if size > 0 && this could be used again
9620 we have to point it back to where it
9622 if (AOP_SIZE(result) > 1 &&
9623 !OP_SYMBOL(left)->remat &&
9624 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9626 int size = AOP_SIZE(result) - 1;
9628 pic16_emitcode("dec","%s",rname);
9633 pic16_freeAsmop(result,NULL,ic,TRUE);
9638 /*-----------------------------------------------------------------*/
9639 /* genFarPointerGet - gget value from far space */
9640 /*-----------------------------------------------------------------*/
9641 static void genFarPointerGet (operand *left,
9642 operand *result, iCode *ic)
9645 sym_link *retype = getSpec(operandType(result));
9647 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9649 pic16_aopOp(left,ic,FALSE);
9651 /* if the operand is already in dptr
9652 then we do nothing else we move the value to dptr */
9653 if (AOP_TYPE(left) != AOP_STR) {
9654 /* if this is remateriazable */
9655 if (AOP_TYPE(left) == AOP_IMMD)
9656 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9657 else { /* we need to get it byte by byte */
9658 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9659 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9660 if (options.model == MODEL_FLAT24)
9662 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9666 /* so dptr know contains the address */
9667 pic16_freeAsmop(left,NULL,ic,TRUE);
9668 pic16_aopOp(result,ic,FALSE);
9670 /* if bit then unpack */
9671 if (IS_BITFIELD(retype))
9672 genUnpackBits(result,left,"dptr",FPOINTER);
9674 size = AOP_SIZE(result);
9678 pic16_emitcode("movx","a,@dptr");
9679 pic16_aopPut(AOP(result),"a",offset++);
9681 pic16_emitcode("inc","dptr");
9685 pic16_freeAsmop(result,NULL,ic,TRUE);
9688 /*-----------------------------------------------------------------*/
9689 /* genCodePointerGet - get value from code space */
9690 /*-----------------------------------------------------------------*/
9691 static void genCodePointerGet (operand *left,
9692 operand *result, iCode *ic)
9695 sym_link *retype = getSpec(operandType(result));
9697 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9699 pic16_aopOp(left,ic,FALSE);
9701 /* if the operand is already in dptr
9702 then we do nothing else we move the value to dptr */
9703 if (AOP_TYPE(left) != AOP_STR) {
9704 /* if this is remateriazable */
9705 if (AOP_TYPE(left) == AOP_IMMD)
9706 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9707 else { /* we need to get it byte by byte */
9708 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9709 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9710 if (options.model == MODEL_FLAT24)
9712 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9716 /* so dptr know contains the address */
9717 pic16_freeAsmop(left,NULL,ic,TRUE);
9718 pic16_aopOp(result,ic,FALSE);
9720 /* if bit then unpack */
9721 if (IS_BITFIELD(retype))
9722 genUnpackBits(result,left,"dptr",CPOINTER);
9724 size = AOP_SIZE(result);
9728 pic16_emitcode("clr","a");
9729 pic16_emitcode("movc","a,@a+dptr");
9730 pic16_aopPut(AOP(result),"a",offset++);
9732 pic16_emitcode("inc","dptr");
9736 pic16_freeAsmop(result,NULL,ic,TRUE);
9739 /*-----------------------------------------------------------------*/
9740 /* genGenPointerGet - gget value from generic pointer space */
9741 /*-----------------------------------------------------------------*/
9742 static void genGenPointerGet (operand *left,
9743 operand *result, iCode *ic)
9745 int size, offset, lit;
9746 sym_link *retype = getSpec(operandType(result));
9748 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9749 pic16_aopOp(left,ic,FALSE);
9750 pic16_aopOp(result,ic,FALSE);
9751 size = AOP_SIZE(result);
9753 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9755 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9757 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9758 // load FSR0 from immediate
9759 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9761 // pic16_loadFSR0( left );
9766 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9768 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9775 else { /* we need to get it byte by byte */
9776 // set up FSR0 with address from left
9777 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9778 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9784 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9786 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9793 /* if bit then unpack */
9794 if (IS_BITFIELD(retype))
9795 genUnpackBits(result,left,"BAD",GPOINTER);
9798 pic16_freeAsmop(left,NULL,ic,TRUE);
9799 pic16_freeAsmop(result,NULL,ic,TRUE);
9803 /*-----------------------------------------------------------------*/
9804 /* genConstPointerGet - get value from const generic pointer space */
9805 /*-----------------------------------------------------------------*/
9806 static void genConstPointerGet (operand *left,
9807 operand *result, iCode *ic)
9809 //sym_link *retype = getSpec(operandType(result));
9810 // symbol *albl = newiTempLabel(NULL); // patch 15
9811 // symbol *blbl = newiTempLabel(NULL); //
9812 // PIC_OPCODE poc; // patch 15
9816 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9817 pic16_aopOp(left,ic,FALSE);
9818 pic16_aopOp(result,ic,TRUE);
9819 size = AOP_SIZE(result);
9821 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9823 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9825 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9826 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9827 pic16_emitpLabel(albl->key);
9829 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9831 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9832 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9833 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9834 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9835 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9837 pic16_emitpLabel(blbl->key);
9839 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9843 // set up table pointer
9844 if( (AOP_TYPE(left) == AOP_PCODE)
9845 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9846 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
9848 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9849 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9850 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9851 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9852 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9853 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9857 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9858 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9859 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9865 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9866 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9870 pic16_freeAsmop(left,NULL,ic,TRUE);
9871 pic16_freeAsmop(result,NULL,ic,TRUE);
9876 /*-----------------------------------------------------------------*/
9877 /* genPointerGet - generate code for pointer get */
9878 /*-----------------------------------------------------------------*/
9879 static void genPointerGet (iCode *ic)
9881 operand *left, *result ;
9882 sym_link *type, *etype;
9885 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9888 result = IC_RESULT(ic) ;
9890 /* depending on the type of pointer we need to
9891 move it to the correct pointer register */
9892 type = operandType(left);
9893 etype = getSpec(type);
9896 if (IS_PTR_CONST(type))
9898 if (IS_CODEPTR(type))
9900 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9902 /* if left is of type of pointer then it is simple */
9903 if (IS_PTR(type) && !IS_FUNC(type->next))
9904 p_type = DCL_TYPE(type);
9906 /* we have to go by the storage class */
9907 p_type = PTR_TYPE(SPEC_OCLS(etype));
9909 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9911 if (SPEC_OCLS(etype)->codesp ) {
9912 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9913 //p_type = CPOINTER ;
9916 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9917 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9918 /*p_type = FPOINTER ;*/
9920 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9921 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9922 /* p_type = PPOINTER; */
9924 if (SPEC_OCLS(etype) == idata )
9925 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9926 /* p_type = IPOINTER; */
9928 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9929 /* p_type = POINTER ; */
9932 /* now that we have the pointer type we assign
9933 the pointer values */
9938 genNearPointerGet (left,result,ic);
9942 genPagedPointerGet(left,result,ic);
9946 genFarPointerGet (left,result,ic);
9950 genConstPointerGet (left,result,ic);
9951 //pic16_emitcodePointerGet (left,result,ic);
9956 if (IS_PTR_CONST(type))
9957 genConstPointerGet (left,result,ic);
9960 genGenPointerGet (left,result,ic);
9964 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9965 "genPointerGet: illegal pointer type");
9971 /*-----------------------------------------------------------------*/
9972 /* genPackBits - generates code for packed bit storage */
9973 /*-----------------------------------------------------------------*/
9974 static void genPackBits (sym_link *etype , operand *result,
9976 char *rname, int p_type)
9984 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9985 blen = SPEC_BLEN(etype);
9986 bstr = SPEC_BSTR(etype);
9988 if(AOP_TYPE(right) == AOP_LIT) {
9989 if((blen == 1) && (bstr < 8)) {
9991 /* it is a single bit, so use the appropriate bit instructions */
9993 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9995 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9996 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9997 if((p_type == POINTER) && (result)) {
9998 /* workaround to reduce the extra lfsr instruction */
10000 pic16_emitpcode(POC_BSF,
10001 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10003 pic16_emitpcode(POC_BCF,
10004 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10009 pic16_emitpcode(POC_BSF,
10010 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10012 pic16_emitpcode(POC_BCF,
10013 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10020 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
10023 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
10025 /* if the bit lenth is less than or */
10026 /* it exactly fits a byte then */
10027 if((shCnt=SPEC_BSTR(etype))
10028 || SPEC_BLEN(etype) <= 8 ) {
10030 /* shift left acc */
10033 /* using PRODL as a temporary register here */
10034 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
10040 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10041 // pic16_emitcode ("mov","b,a");
10042 // pic16_emitcode("mov","a,@%s",rname);
10046 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10047 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
10048 (unsigned char)(0xff >> (8-bstr))) ));
10049 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
10050 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10057 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10058 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10063 if ( SPEC_BLEN(etype) <= 8 )
10066 pic16_emitcode("inc","%s",rname);
10067 rLen = SPEC_BLEN(etype) ;
10071 /* now generate for lengths greater than one byte */
10074 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
10084 pic16_emitcode("mov","@%s,a",rname);
10086 pic16_emitcode("mov","@%s,%s",rname,l);
10091 pic16_emitcode("movx","@dptr,a");
10096 DEBUGpic16_emitcode(";lcall","__gptrput");
10099 pic16_emitcode ("inc","%s",rname);
10104 /* last last was not complete */
10106 /* save the byte & read byte */
10109 pic16_emitcode ("mov","b,a");
10110 pic16_emitcode("mov","a,@%s",rname);
10114 pic16_emitcode ("mov","b,a");
10115 pic16_emitcode("movx","a,@dptr");
10119 pic16_emitcode ("push","b");
10120 pic16_emitcode ("push","acc");
10121 pic16_emitcode ("lcall","__gptrget");
10122 pic16_emitcode ("pop","b");
10126 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
10127 pic16_emitcode ("orl","a,b");
10130 if (p_type == GPOINTER)
10131 pic16_emitcode("pop","b");
10136 pic16_emitcode("mov","@%s,a",rname);
10140 pic16_emitcode("movx","@dptr,a");
10144 DEBUGpic16_emitcode(";lcall","__gptrput");
10148 /*-----------------------------------------------------------------*/
10149 /* genDataPointerSet - remat pointer to data space */
10150 /*-----------------------------------------------------------------*/
10151 static void genDataPointerSet(operand *right,
10155 int size, offset = 0, resoffset=0 ;
10157 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10158 pic16_aopOp(right,ic,FALSE);
10160 size = AOP_SIZE(right);
10162 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10165 if ( AOP_TYPE(result) == AOP_PCODE) {
10166 fprintf(stderr,"genDataPointerSet %s, %d\n",
10167 AOP(result)->aopu.pcop->name,
10168 (AOP(result)->aopu.pcop->type == PO_DIR)?
10169 PCOR(AOP(result)->aopu.pcop)->instance:
10170 PCOI(AOP(result)->aopu.pcop)->offset);
10174 if(AOP(result)->aopu.pcop->type == PO_DIR)
10175 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
10178 if (AOP_TYPE(right) == AOP_LIT) {
10179 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
10181 lit = lit >> (8*offset);
10183 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
10184 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
10186 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
10189 mov2w(AOP(right), offset);
10190 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
10196 pic16_freeAsmop(right,NULL,ic,TRUE);
10201 /*-----------------------------------------------------------------*/
10202 /* genNearPointerSet - pic16_emitcode for near pointer put */
10203 /*-----------------------------------------------------------------*/
10204 static void genNearPointerSet (operand *right,
10211 sym_link *ptype = operandType(result);
10212 sym_link *resetype;
10214 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10215 retype= getSpec(operandType(right));
10216 resetype = getSpec(operandType(result));
10218 pic16_aopOp(result,ic,FALSE);
10220 /* if the result is rematerializable &
10221 * in data space & not a bit variable */
10223 /* and result is not a bit variable */
10224 if (AOP_TYPE(result) == AOP_PCODE
10225 // && AOP_TYPE(result) == AOP_IMMD
10226 && DCL_TYPE(ptype) == POINTER
10227 && !IS_BITFIELD(retype)
10228 && !IS_BITFIELD(resetype)) {
10230 genDataPointerSet (right,result,ic);
10231 pic16_freeAsmop(result,NULL,ic,TRUE);
10235 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10236 pic16_aopOp(right,ic,FALSE);
10237 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10239 /* if the value is already in a pointer register
10240 * then don't need anything more */
10241 if (!AOP_INPREG(AOP(result))) {
10242 /* otherwise get a free pointer register */
10243 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10245 if( (AOP_TYPE(result) == AOP_PCODE)
10246 && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10247 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10249 if(!IS_BITFIELD(resetype))
10250 pic16_loadFSR0( result ); // patch 10
10252 // set up FSR0 with address of result
10253 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10254 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10259 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10261 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10263 /* if bitfield then unpack the bits */
10264 if (IS_BITFIELD(resetype)) {
10265 genPackBits (resetype, result, right, NULL, POINTER);
10267 /* we have can just get the values */
10268 int size = AOP_SIZE(right);
10271 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10273 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10276 //pic16_emitcode("mov","@%s,a",rname);
10277 pic16_emitcode("movf","indf0,w ;1");
10280 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
10281 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
10283 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
10285 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
10287 } else { // no literal //
10289 pic16_emitpcode(POC_MOVFF, //
10290 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10291 pic16_popCopyReg(&pic16_pc_postinc0))); //
10293 pic16_emitpcode(POC_MOVFF, //
10294 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10295 pic16_popCopyReg(&pic16_pc_indf0))); //
10303 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10304 /* now some housekeeping stuff */
10306 /* we had to allocate for this iCode */
10307 pic16_freeAsmop(NULL,aop,ic,TRUE);
10309 /* we did not allocate which means left
10310 * already in a pointer register, then
10311 * if size > 0 && this could be used again
10312 * we have to point it back to where it
10314 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10315 if (AOP_SIZE(right) > 1
10316 && !OP_SYMBOL(result)->remat
10317 && ( OP_SYMBOL(result)->liveTo > ic->seq
10320 int size = AOP_SIZE(right) - 1;
10323 pic16_emitcode("decf","fsr0,f");
10324 //pic16_emitcode("dec","%s",rname);
10328 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10331 pic16_freeAsmop(right,NULL,ic,TRUE);
10332 pic16_freeAsmop(result,NULL,ic,TRUE);
10335 /*-----------------------------------------------------------------*/
10336 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
10337 /*-----------------------------------------------------------------*/
10338 static void genPagedPointerSet (operand *right,
10343 regs *preg = NULL ;
10347 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10349 retype= getSpec(operandType(right));
10351 pic16_aopOp(result,ic,FALSE);
10353 /* if the value is already in a pointer register
10354 then don't need anything more */
10355 if (!AOP_INPREG(AOP(result))) {
10356 /* otherwise get a free pointer register */
10358 preg = getFreePtr(ic,&aop,FALSE);
10359 pic16_emitcode("mov","%s,%s",
10361 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10362 rname = preg->name ;
10364 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10366 pic16_freeAsmop(result,NULL,ic,TRUE);
10367 pic16_aopOp (right,ic,FALSE);
10369 /* if bitfield then unpack the bits */
10370 if (IS_BITFIELD(retype))
10371 genPackBits (retype,result,right,rname,PPOINTER);
10373 /* we have can just get the values */
10374 int size = AOP_SIZE(right);
10378 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10381 pic16_emitcode("movx","@%s,a",rname);
10384 pic16_emitcode("inc","%s",rname);
10390 /* now some housekeeping stuff */
10392 /* we had to allocate for this iCode */
10393 pic16_freeAsmop(NULL,aop,ic,TRUE);
10395 /* we did not allocate which means left
10396 already in a pointer register, then
10397 if size > 0 && this could be used again
10398 we have to point it back to where it
10400 if (AOP_SIZE(right) > 1 &&
10401 !OP_SYMBOL(result)->remat &&
10402 ( OP_SYMBOL(result)->liveTo > ic->seq ||
10404 int size = AOP_SIZE(right) - 1;
10406 pic16_emitcode("dec","%s",rname);
10411 pic16_freeAsmop(right,NULL,ic,TRUE);
10416 /*-----------------------------------------------------------------*/
10417 /* genFarPointerSet - set value from far space */
10418 /*-----------------------------------------------------------------*/
10419 static void genFarPointerSet (operand *right,
10420 operand *result, iCode *ic)
10423 sym_link *retype = getSpec(operandType(right));
10425 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10426 pic16_aopOp(result,ic,FALSE);
10428 /* if the operand is already in dptr
10429 then we do nothing else we move the value to dptr */
10430 if (AOP_TYPE(result) != AOP_STR) {
10431 /* if this is remateriazable */
10432 if (AOP_TYPE(result) == AOP_IMMD)
10433 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10434 else { /* we need to get it byte by byte */
10435 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10436 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10437 if (options.model == MODEL_FLAT24)
10439 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10443 /* so dptr know contains the address */
10444 pic16_freeAsmop(result,NULL,ic,TRUE);
10445 pic16_aopOp(right,ic,FALSE);
10447 /* if bit then unpack */
10448 if (IS_BITFIELD(retype))
10449 genPackBits(retype,result,right,"dptr",FPOINTER);
10451 size = AOP_SIZE(right);
10455 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10457 pic16_emitcode("movx","@dptr,a");
10459 pic16_emitcode("inc","dptr");
10463 pic16_freeAsmop(right,NULL,ic,TRUE);
10466 /*-----------------------------------------------------------------*/
10467 /* genGenPointerSet - set value from generic pointer space */
10468 /*-----------------------------------------------------------------*/
10469 static void genGenPointerSet (operand *right,
10470 operand *result, iCode *ic)
10472 int i, size, offset, lit;
10473 sym_link *retype = getSpec(operandType(right));
10475 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10477 pic16_aopOp(result,ic,FALSE);
10478 pic16_aopOp(right,ic,FALSE);
10479 size = AOP_SIZE(right);
10482 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10484 /* if the operand is already in dptr
10485 then we do nothing else we move the value to dptr */
10486 if (AOP_TYPE(result) != AOP_STR) {
10487 /* if this is remateriazable */
10488 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10489 // WARNING: anythig until "else" is untested!
10490 if (AOP_TYPE(result) == AOP_IMMD) {
10491 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10492 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10493 // load FSR0 from immediate
10494 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10498 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10500 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10506 else { /* we need to get it byte by byte */
10507 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10508 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10510 // set up FSR0 with address of result
10511 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10512 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10514 /* hack hack! see if this the FSR. If so don't load W */
10515 if(AOP_TYPE(right) != AOP_ACC) {
10517 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10519 if(AOP_TYPE(right) == AOP_LIT)
10522 // note: pic16_popGet handles sign extension
10523 for(i=0;i<size;i++) {
10524 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10526 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10528 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10533 for(i=0;i<size;i++) {
10535 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10536 pic16_popCopyReg(&pic16_pc_postinc0)));
10538 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10539 pic16_popCopyReg(&pic16_pc_indf0)));
10545 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10546 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10548 } // if (AOP_TYPE(result) != AOP_IMMD)
10550 } // if (AOP_TYPE(result) != AOP_STR)
10551 /* so dptr know contains the address */
10554 /* if bit then unpack */
10555 if (IS_BITFIELD(retype))
10556 genPackBits(retype,result,right,"dptr",GPOINTER);
10558 size = AOP_SIZE(right);
10561 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
10563 // set up FSR0 with address of result
10564 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10565 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10568 if (AOP_TYPE(right) == AOP_LIT) {
10569 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10571 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10573 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10575 } else { // no literal
10577 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10579 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10587 pic16_freeAsmop(right,NULL,ic,TRUE);
10588 pic16_freeAsmop(result,NULL,ic,TRUE);
10591 /*-----------------------------------------------------------------*/
10592 /* genPointerSet - stores the value into a pointer location */
10593 /*-----------------------------------------------------------------*/
10594 static void genPointerSet (iCode *ic)
10596 operand *right, *result ;
10597 sym_link *type, *etype;
10600 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10602 right = IC_RIGHT(ic);
10603 result = IC_RESULT(ic) ;
10605 /* depending on the type of pointer we need to
10606 move it to the correct pointer register */
10607 type = operandType(result);
10608 etype = getSpec(type);
10609 /* if left is of type of pointer then it is simple */
10610 if (IS_PTR(type) && !IS_FUNC(type->next)) {
10611 p_type = DCL_TYPE(type);
10614 /* we have to go by the storage class */
10615 p_type = PTR_TYPE(SPEC_OCLS(etype));
10617 /* if (SPEC_OCLS(etype)->codesp ) { */
10618 /* p_type = CPOINTER ; */
10621 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10622 /* p_type = FPOINTER ; */
10624 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10625 /* p_type = PPOINTER ; */
10627 /* if (SPEC_OCLS(etype) == idata ) */
10628 /* p_type = IPOINTER ; */
10630 /* p_type = POINTER ; */
10633 /* now that we have the pointer type we assign
10634 the pointer values */
10639 genNearPointerSet (right,result,ic);
10643 genPagedPointerSet (right,result,ic);
10647 genFarPointerSet (right,result,ic);
10651 genGenPointerSet (right,result,ic);
10655 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10656 "genPointerSet: illegal pointer type");
10660 /*-----------------------------------------------------------------*/
10661 /* genIfx - generate code for Ifx statement */
10662 /*-----------------------------------------------------------------*/
10663 static void genIfx (iCode *ic, iCode *popIc)
10665 operand *cond = IC_COND(ic);
10668 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10670 pic16_aopOp(cond,ic,FALSE);
10672 /* get the value into acc */
10673 if (AOP_TYPE(cond) != AOP_CRY)
10674 pic16_toBoolean(cond);
10677 /* the result is now in the accumulator */
10678 pic16_freeAsmop(cond,NULL,ic,TRUE);
10680 /* if there was something to be popped then do it */
10684 /* if the condition is a bit variable */
10685 if (isbit && IS_ITEMP(cond) &&
10687 genIfxJump(ic,SPIL_LOC(cond)->rname);
10688 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10691 if (isbit && !IS_ITEMP(cond))
10692 genIfxJump(ic,OP_SYMBOL(cond)->rname);
10694 genIfxJump(ic,"a");
10700 /*-----------------------------------------------------------------*/
10701 /* genAddrOf - generates code for address of */
10702 /*-----------------------------------------------------------------*/
10703 static void genAddrOf (iCode *ic)
10705 operand *result, *left;
10707 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
10708 pCodeOp *pcop0, *pcop1, *pcop2;
10710 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10712 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10713 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10715 sym = OP_SYMBOL( left );
10717 size = AOP_SIZE(IC_RESULT(ic));
10721 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
10726 // if(pic16_debug_verbose) {
10727 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10728 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10731 /* Assume that what we want the address of is in data space
10732 * since there is no stack on the PIC, yet! -- VR */
10734 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10737 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10740 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10744 pic16_emitpcode(POC_MOVLW, pcop0);
10745 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10746 pic16_emitpcode(POC_MOVLW, pcop1);
10747 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10748 pic16_emitpcode(POC_MOVLW, pcop2);
10749 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10752 pic16_emitpcode(POC_MOVLW, pcop0);
10753 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10754 pic16_emitpcode(POC_MOVLW, pcop1);
10755 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10757 pic16_emitpcode(POC_MOVLW, pcop0);
10758 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10761 pic16_freeAsmop(result,NULL,ic,TRUE);
10762 pic16_freeAsmop(left, NULL, ic, FALSE);
10767 /*-----------------------------------------------------------------*/
10768 /* genFarFarAssign - assignment when both are in far space */
10769 /*-----------------------------------------------------------------*/
10770 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10772 int size = AOP_SIZE(right);
10775 /* first push the right side on to the stack */
10777 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10779 pic16_emitcode ("push","acc");
10782 pic16_freeAsmop(right,NULL,ic,FALSE);
10783 /* now assign DPTR to result */
10784 pic16_aopOp(result,ic,FALSE);
10785 size = AOP_SIZE(result);
10787 pic16_emitcode ("pop","acc");
10788 pic16_aopPut(AOP(result),"a",--offset);
10790 pic16_freeAsmop(result,NULL,ic,FALSE);
10795 /*-----------------------------------------------------------------*/
10796 /* genAssign - generate code for assignment */
10797 /*-----------------------------------------------------------------*/
10798 static void genAssign (iCode *ic)
10800 operand *result, *right;
10801 int size, offset,know_W;
10802 unsigned long lit = 0L;
10804 result = IC_RESULT(ic);
10805 right = IC_RIGHT(ic) ;
10807 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10809 /* if they are the same */
10810 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10813 pic16_aopOp(right,ic,FALSE);
10814 pic16_aopOp(result,ic,TRUE);
10816 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10818 /* if they are the same registers */
10819 if (pic16_sameRegs(AOP(right),AOP(result)))
10822 /* if the result is a bit */
10823 if (AOP_TYPE(result) == AOP_CRY) {
10824 /* if the right size is a literal then
10825 we know what the value is */
10826 if (AOP_TYPE(right) == AOP_LIT) {
10828 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10829 pic16_popGet(AOP(result),0));
10831 if (((int) operandLitValue(right)))
10832 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10833 AOP(result)->aopu.aop_dir,
10834 AOP(result)->aopu.aop_dir);
10836 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10837 AOP(result)->aopu.aop_dir,
10838 AOP(result)->aopu.aop_dir);
10842 /* the right is also a bit variable */
10843 if (AOP_TYPE(right) == AOP_CRY) {
10844 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10845 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10846 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10848 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10849 AOP(result)->aopu.aop_dir,
10850 AOP(result)->aopu.aop_dir);
10851 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10852 AOP(right)->aopu.aop_dir,
10853 AOP(right)->aopu.aop_dir);
10854 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10855 AOP(result)->aopu.aop_dir,
10856 AOP(result)->aopu.aop_dir);
10860 /* we need to or */
10861 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10862 pic16_toBoolean(right);
10864 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10865 //pic16_aopPut(AOP(result),"a",0);
10869 /* bit variables done */
10871 size = AOP_SIZE(result);
10874 if(AOP_TYPE(right) == AOP_LIT) {
10875 if(!IS_FLOAT(operandType( right )))
10876 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10879 unsigned long lit_int;
10883 /* take care if literal is a float */
10884 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10885 lit = info.lit_int;
10889 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10890 // sizeof(unsigned long int), sizeof(float));
10892 if(AOP_TYPE(right) != AOP_LIT
10893 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10894 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10895 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
10897 // set up table pointer
10898 if( (AOP_TYPE(right) == AOP_PCODE)
10899 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10900 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10902 fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
10903 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10904 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10905 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10906 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10907 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10908 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10910 fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
10911 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10912 pic16_popCopyReg(&pic16_pc_tblptrl)));
10913 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10914 pic16_popCopyReg(&pic16_pc_tblptrh)));
10915 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10916 pic16_popCopyReg(&pic16_pc_tblptru)));
10919 size = min(AOP_SIZE(right), AOP_SIZE(result));
10921 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10922 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10923 pic16_popGet(AOP(result),offset)));
10927 if(AOP_SIZE(result) > AOP_SIZE(right)) {
10928 size = AOP_SIZE(result) - AOP_SIZE(right);
10930 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10940 /* VR - What is this?! */
10941 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10942 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10943 if(aopIdx(AOP(result),0) == 4) {
10945 /* this is a workaround to save value of right into wreg too,
10946 * value of wreg is going to be used later */
10947 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10948 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10949 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10953 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10959 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10960 if(AOP_TYPE(right) == AOP_LIT) {
10962 if(know_W != (lit&0xff))
10963 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10965 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10967 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10971 } else if (AOP_TYPE(right) == AOP_CRY) {
10972 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10974 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10975 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10977 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10978 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10979 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10981 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10984 /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10985 normally should work, but mind that the W register live range
10986 is not checked, so if the code generator assumes that the W
10987 is already loaded after such a pair, wrong code will be generated.
10989 Checking the live range is the next step.
10990 This is experimental code yet and has not been fully tested yet.
10991 USE WITH CARE. Revert to old code by setting 0 to the condition above.
10992 Vangelis Rokas 030603 (vrokas@otenet.gr) */
10994 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10996 /* This is the old code, which is assumed(?!) that works fine(!?) */
10998 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10999 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11008 pic16_freeAsmop (right,NULL,ic,FALSE);
11009 pic16_freeAsmop (result,NULL,ic,TRUE);
11012 /*-----------------------------------------------------------------*/
11013 /* genJumpTab - generates code for jump table */
11014 /*-----------------------------------------------------------------*/
11015 static void genJumpTab (iCode *ic)
11020 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11022 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
11023 /* get the condition into accumulator */
11024 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
11026 /* multiply by three */
11027 pic16_emitcode("add","a,acc");
11028 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
11030 jtab = newiTempLabel(NULL);
11031 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
11032 pic16_emitcode("jmp","@a+dptr");
11033 pic16_emitcode("","%05d_DS_:",jtab->key+100);
11035 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
11036 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
11038 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
11039 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
11040 pic16_emitpLabel(jtab->key);
11042 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
11044 /* now generate the jump labels */
11045 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
11046 jtab = setNextItem(IC_JTLABELS(ic))) {
11047 pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
11048 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
11054 /*-----------------------------------------------------------------*/
11055 /* genMixedOperation - gen code for operators between mixed types */
11056 /*-----------------------------------------------------------------*/
11058 TSD - Written for the PIC port - but this unfortunately is buggy.
11059 This routine is good in that it is able to efficiently promote
11060 types to different (larger) sizes. Unfortunately, the temporary
11061 variables that are optimized out by this routine are sometimes
11062 used in other places. So until I know how to really parse the
11063 iCode tree, I'm going to not be using this routine :(.
11065 static int genMixedOperation (iCode *ic)
11068 operand *result = IC_RESULT(ic);
11069 sym_link *ctype = operandType(IC_LEFT(ic));
11070 operand *right = IC_RIGHT(ic);
11076 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
11078 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11084 nextright = IC_RIGHT(nextic);
11085 nextleft = IC_LEFT(nextic);
11086 nextresult = IC_RESULT(nextic);
11088 pic16_aopOp(right,ic,FALSE);
11089 pic16_aopOp(result,ic,FALSE);
11090 pic16_aopOp(nextright, nextic, FALSE);
11091 pic16_aopOp(nextleft, nextic, FALSE);
11092 pic16_aopOp(nextresult, nextic, FALSE);
11094 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
11096 operand *t = right;
11100 pic16_emitcode(";remove right +","");
11102 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
11104 operand *t = right;
11108 pic16_emitcode(";remove left +","");
11112 big = AOP_SIZE(nextleft);
11113 small = AOP_SIZE(nextright);
11115 switch(nextic->op) {
11118 pic16_emitcode(";optimize a +","");
11119 /* if unsigned or not an integral type */
11120 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
11121 pic16_emitcode(";add a bit to something","");
11124 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
11126 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
11127 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
11128 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
11130 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
11138 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11139 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11140 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11143 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11145 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11146 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
11147 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
11148 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11149 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
11152 pic16_emitcode("rlf","known_zero,w");
11159 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11160 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11161 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11163 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11173 pic16_freeAsmop(right,NULL,ic,TRUE);
11174 pic16_freeAsmop(result,NULL,ic,TRUE);
11175 pic16_freeAsmop(nextright,NULL,ic,TRUE);
11176 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
11178 nextic->generated = 1;
11185 /*-----------------------------------------------------------------*/
11186 /* genCast - gen code for casting */
11187 /*-----------------------------------------------------------------*/
11188 static void genCast (iCode *ic)
11190 operand *result = IC_RESULT(ic);
11191 sym_link *ctype = operandType(IC_LEFT(ic));
11192 sym_link *rtype = operandType(IC_RIGHT(ic));
11193 operand *right = IC_RIGHT(ic);
11196 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11197 /* if they are equivalent then do nothing */
11198 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
11201 pic16_aopOp(right,ic,FALSE) ;
11202 pic16_aopOp(result,ic,FALSE);
11204 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11206 /* if the result is a bit */
11207 if (AOP_TYPE(result) == AOP_CRY) {
11209 /* if the right size is a literal then
11210 * we know what the value is */
11211 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11213 if (AOP_TYPE(right) == AOP_LIT) {
11214 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11215 pic16_popGet(AOP(result),0));
11217 if (((int) operandLitValue(right)))
11218 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
11219 AOP(result)->aopu.aop_dir,
11220 AOP(result)->aopu.aop_dir);
11222 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
11223 AOP(result)->aopu.aop_dir,
11224 AOP(result)->aopu.aop_dir);
11228 /* the right is also a bit variable */
11229 if (AOP_TYPE(right) == AOP_CRY) {
11231 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11233 pic16_emitcode("clrc","");
11234 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11235 AOP(right)->aopu.aop_dir,
11236 AOP(right)->aopu.aop_dir);
11237 pic16_aopPut(AOP(result),"c",0);
11241 /* we need to or */
11242 if (AOP_TYPE(right) == AOP_REG) {
11243 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
11244 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
11245 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
11247 pic16_toBoolean(right);
11248 pic16_aopPut(AOP(result),"a",0);
11252 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11255 size = AOP_SIZE(result);
11257 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11259 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
11260 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11261 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
11264 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11269 /* if they are the same size : or less */
11270 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11272 /* if they are in the same place */
11273 if (pic16_sameRegs(AOP(right),AOP(result)))
11276 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11278 if (IS_PTR_CONST(rtype))
11280 if (IS_CODEPTR(rtype))
11282 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11285 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11287 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11289 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11292 if(AOP_TYPE(right) == AOP_IMMD) {
11293 pCodeOp *pcop0, *pcop1, *pcop2;
11294 symbol *sym = OP_SYMBOL( right );
11296 size = AOP_SIZE(result);
11298 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11300 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11302 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11305 pic16_emitpcode(POC_MOVLW, pcop0);
11306 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11307 pic16_emitpcode(POC_MOVLW, pcop1);
11308 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11309 pic16_emitpcode(POC_MOVLW, pcop2);
11310 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11313 pic16_emitpcode(POC_MOVLW, pcop0);
11314 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11315 pic16_emitpcode(POC_MOVLW, pcop1);
11316 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11318 pic16_emitpcode(POC_MOVLW, pcop0);
11319 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11323 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11324 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11325 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11326 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11327 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11328 if(AOP_SIZE(result) <2)
11329 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11331 /* if they in different places then copy */
11332 size = AOP_SIZE(result);
11335 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11336 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11343 /* if the result is of type pointer */
11344 if (IS_PTR(ctype)) {
11346 sym_link *type = operandType(right);
11347 sym_link *etype = getSpec(type);
11349 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
11351 /* pointer to generic pointer */
11352 if (IS_GENPTR(ctype)) {
11356 p_type = DCL_TYPE(type);
11358 /* we have to go by the storage class */
11359 p_type = PTR_TYPE(SPEC_OCLS(etype));
11361 /* if (SPEC_OCLS(etype)->codesp ) */
11362 /* p_type = CPOINTER ; */
11364 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11365 /* p_type = FPOINTER ; */
11367 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11368 /* p_type = PPOINTER; */
11370 /* if (SPEC_OCLS(etype) == idata ) */
11371 /* p_type = IPOINTER ; */
11373 /* p_type = POINTER ; */
11376 /* the first two bytes are known */
11377 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
11378 size = GPTRSIZE - 1;
11381 if(offset < AOP_SIZE(right)) {
11382 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
11383 if ((AOP_TYPE(right) == AOP_PCODE) &&
11384 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11385 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11386 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11388 pic16_aopPut(AOP(result),
11389 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11393 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11396 /* the last byte depending on type */
11400 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11403 pic16_emitcode(";BUG!? ","%d",__LINE__);
11407 pic16_emitcode(";BUG!? ","%d",__LINE__);
11411 pic16_emitcode(";BUG!? ","%d",__LINE__);
11416 /* this should never happen */
11417 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11418 "got unknown pointer type");
11421 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
11425 /* just copy the pointers */
11426 size = AOP_SIZE(result);
11429 pic16_aopPut(AOP(result),
11430 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11439 /* so we now know that the size of destination is greater
11440 than the size of the source.
11441 Now, if the next iCode is an operator then we might be
11442 able to optimize the operation without performing a cast.
11444 if(genMixedOperation(ic))
11447 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11449 /* we move to result for the size of source */
11450 size = AOP_SIZE(right);
11453 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11454 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11455 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11459 /* now depending on the sign of the destination */
11460 size = AOP_SIZE(result) - AOP_SIZE(right);
11461 /* if unsigned or not an integral type */
11462 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11464 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11466 /* we need to extend the sign :( */
11469 /* Save one instruction of casting char to int */
11470 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11471 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11472 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
11474 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11477 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11479 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11481 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
11484 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
11489 pic16_freeAsmop(right,NULL,ic,TRUE);
11490 pic16_freeAsmop(result,NULL,ic,TRUE);
11494 /*-----------------------------------------------------------------*/
11495 /* genDjnz - generate decrement & jump if not zero instrucion */
11496 /*-----------------------------------------------------------------*/
11497 static int genDjnz (iCode *ic, iCode *ifx)
11499 symbol *lbl, *lbl1;
11500 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11505 /* if the if condition has a false label
11506 then we cannot save */
11510 /* if the minus is not of the form
11512 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11513 !IS_OP_LITERAL(IC_RIGHT(ic)))
11516 if (operandLitValue(IC_RIGHT(ic)) != 1)
11519 /* if the size of this greater than one then no
11521 if (getSize(operandType(IC_RESULT(ic))) > 1)
11524 /* otherwise we can save BIG */
11525 lbl = newiTempLabel(NULL);
11526 lbl1= newiTempLabel(NULL);
11528 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11530 if (IS_AOP_PREG(IC_RESULT(ic))) {
11531 pic16_emitcode("dec","%s",
11532 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11533 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11534 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11538 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11539 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11541 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11542 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
11545 /* pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11546 /* pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11547 /* pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11548 /* pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11551 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11552 ifx->generated = 1;
11556 /*-----------------------------------------------------------------*/
11557 /* genReceive - generate code for a receive iCode */
11558 /*-----------------------------------------------------------------*/
11559 static void genReceive (iCode *ic)
11561 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11564 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11565 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
11567 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11569 if (isOperandInFarSpace(IC_RESULT(ic)) &&
11570 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11571 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11573 int size = getSize(operandType(IC_RESULT(ic)));
11574 int offset = pic16_fReturnSizePic - size;
11578 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11579 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11583 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
11585 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11586 size = AOP_SIZE(IC_RESULT(ic));
11589 pic16_emitcode ("pop","acc");
11590 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11593 DEBUGpic16_emitcode ("; ***","2 %s %d",__FUNCTION__,__LINE__);
11596 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11598 assignResultValue(IC_RESULT(ic), 0);
11601 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11604 /*-----------------------------------------------------------------*/
11605 /* genDummyRead - generate code for dummy read of volatiles */
11606 /*-----------------------------------------------------------------*/
11608 genDummyRead (iCode * ic)
11610 pic16_emitcode ("; genDummyRead","");
11611 pic16_emitcode ("; not implemented","");
11616 /*-----------------------------------------------------------------*/
11617 /* genpic16Code - generate code for pic16 based controllers */
11618 /*-----------------------------------------------------------------*/
11620 * At this point, ralloc.c has gone through the iCode and attempted
11621 * to optimize in a way suitable for a PIC. Now we've got to generate
11622 * PIC instructions that correspond to the iCode.
11624 * Once the instructions are generated, we'll pass through both the
11625 * peep hole optimizer and the pCode optimizer.
11626 *-----------------------------------------------------------------*/
11628 void genpic16Code (iCode *lic)
11633 lineHead = lineCurr = NULL;
11635 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11636 pic16_addpBlock(pb);
11639 /* if debug information required */
11640 if (options.debug && currFunc) {
11642 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11647 for (ic = lic ; ic ; ic = ic->next ) {
11649 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11650 if ( cln != ic->lineno ) {
11651 if ( options.debug ) {
11652 debugFile->writeCLine (ic);
11655 if(!options.noCcodeInAsm) {
11656 pic16_addpCode2pBlock(pb,
11657 pic16_newpCodeCSource(ic->lineno, ic->filename,
11658 printCLine(ic->filename, ic->lineno)));
11664 if(options.iCodeInAsm) {
11666 /* insert here code to print iCode as comment */
11667 l = Safe_strdup(printILine(ic));
11668 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11671 /* if the result is marked as
11672 spilt and rematerializable or code for
11673 this has already been generated then
11675 if (resultRemat(ic) || ic->generated )
11678 /* depending on the operation */
11697 /* IPOP happens only when trying to restore a
11698 spilt live range, if there is an ifx statement
11699 following this pop then the if statement might
11700 be using some of the registers being popped which
11701 would destroy the contents of the register so
11702 we need to check for this condition and handle it */
11704 ic->next->op == IFX &&
11705 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
11706 genIfx (ic->next,ic);
11724 genEndFunction (ic);
11740 pic16_genPlus (ic) ;
11744 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11745 pic16_genMinus (ic);
11761 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
11765 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11772 /* note these two are xlated by algebraic equivalence
11773 during parsing SDCC.y */
11774 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11775 "got '>=' or '<=' shouldn't have come here");
11779 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11791 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11795 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11799 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11823 genRightShift (ic);
11826 case GET_VALUE_AT_ADDRESS:
11831 if (POINTER_SET(ic))
11858 addSet(&_G.sendSet,ic);
11861 case DUMMY_READ_VOLATILE:
11871 /* now we are ready to call the
11872 peep hole optimizer */
11873 if (!options.nopeep) {
11874 peepHole (&lineHead);
11876 /* now do the actual printing */
11877 printLine (lineHead,codeOutFile);
11880 DFPRINTF((stderr,"printing pBlock\n\n"));
11881 pic16_printpBlock(stdout,pb);