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;
1127 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1128 __FUNCTION__,__LINE__,
1129 sym->usl.spillLoc->rname,
1130 sym->rname, sym->usl.spillLoc->offset);
1133 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1134 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1135 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1137 sym->usl.spillLoc->offset, op);
1138 aop->size = getSize(sym->type);
1144 sym_link *type = operandType(op);
1146 if(IS_PTR_CONST(type))
1148 if(IS_CODEPTR(type))
1150 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1153 /* must be in a register */
1154 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1155 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1156 aop->size = sym->nRegs;
1157 for ( i = 0 ; i < sym->nRegs ;i++)
1158 aop->aopu.aop_reg[i] = sym->regs[i];
1161 /*-----------------------------------------------------------------*/
1162 /* pic16_freeAsmop - free up the asmop given to an operand */
1163 /*----------------------------------------------------------------*/
1164 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1181 /* depending on the asmop type only three cases need work AOP_RO
1182 , AOP_R1 && AOP_STK */
1184 switch (aop->type) {
1186 if (_G.fsr0Pushed ) {
1188 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1189 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1190 // pic16_emitcode ("pop","ar0");
1194 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1198 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1204 pic16_emitcode ("pop","ar0");
1208 bitVectUnSetBit(ic->rUsed,R0_IDX);
1214 pic16_emitcode ("pop","ar1");
1218 bitVectUnSetBit(ic->rUsed,R1_IDX);
1224 int stk = aop->aopu.aop_stk + aop->size;
1225 bitVectUnSetBit(ic->rUsed,R0_IDX);
1226 bitVectUnSetBit(ic->rUsed,R1_IDX);
1228 getFreePtr(ic,&aop,FALSE);
1230 if (options.stack10bit)
1232 /* I'm not sure what to do here yet... */
1235 "*** Warning: probably generating bad code for "
1236 "10 bit stack mode.\n");
1240 pic16_emitcode ("mov","a,_bp");
1241 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1242 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1244 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1248 pic16_emitcode("pop","acc");
1249 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1251 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1254 pic16_freeAsmop(op,NULL,ic,TRUE);
1256 pic16_emitcode("pop","ar0");
1261 pic16_emitcode("pop","ar1");
1269 /* all other cases just dealloc */
1273 OP_SYMBOL(op)->aop = NULL;
1274 /* if the symbol has a spill */
1276 SPIL_LOC(op)->aop = NULL;
1281 /*-----------------------------------------------------------------*/
1282 /* pic16_aopGet - for fetching value of the aop */
1283 /*-----------------------------------------------------------------*/
1284 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1289 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1291 /* offset is greater than size then zero */
1292 if (offset > (aop->size - 1) &&
1293 aop->type != AOP_LIT)
1296 /* depending on type */
1297 switch (aop->type) {
1301 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1302 rs = Safe_calloc(1, strlen(s)+1);
1307 /* if we need to increment it */
1308 while (offset > aop->coff)
1310 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1314 while (offset < aop->coff)
1316 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1322 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1323 return (dname ? "acc" : "a");
1325 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1326 rs = Safe_calloc (1, strlen (s) + 1);
1334 sprintf (s,"%s",aop->aopu.aop_immd);
1337 sprintf(s,"(%s >> %d)",
1342 aop->aopu.aop_immd);
1343 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1344 rs = Safe_calloc(1,strlen(s)+1);
1350 sprintf(s,"(%s + %d)",
1353 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1355 sprintf(s,"%s",aop->aopu.aop_dir);
1356 rs = Safe_calloc(1,strlen(s)+1);
1362 // return aop->aopu.aop_reg[offset]->dname;
1364 return aop->aopu.aop_reg[offset]->name;
1367 //pic16_emitcode(";","%d",__LINE__);
1368 return aop->aopu.aop_dir;
1371 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1372 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1374 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1375 rs = Safe_strdup("WREG");
1379 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1380 rs = Safe_calloc(1,strlen(s)+1);
1385 aop->coff = offset ;
1386 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1389 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1391 return aop->aopu.aop_str[offset];
1395 pCodeOp *pcop = aop->aopu.pcop;
1396 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1398 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1399 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1400 sprintf(s,"%s", pcop->name);
1402 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1405 rs = Safe_calloc(1,strlen(s)+1);
1410 // pCodeOp *pcop = aop->aop
1415 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1416 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1417 "aopget got unsupported aop->type");
1422 /*-----------------------------------------------------------------*/
1423 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1424 /*-----------------------------------------------------------------*/
1425 pCodeOp *pic16_popGetTempReg(void)
1430 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1435 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1436 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1437 PCOR(pcop)->r->wasUsed=1;
1438 PCOR(pcop)->r->isFree=0;
1440 /* push value on stack */
1441 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1449 /*-----------------------------------------------------------------*/
1450 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1451 /*-----------------------------------------------------------------*/
1452 void pic16_popReleaseTempReg(pCodeOp *pcop)
1454 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1456 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1457 PCOR(pcop)->r->isFree = 1;
1459 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1462 /*-----------------------------------------------------------------*/
1463 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1464 /*-----------------------------------------------------------------*/
1465 pCodeOp *pic16_popGetLabel(unsigned int key)
1468 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1473 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1476 /*-----------------------------------------------------------------*/
1477 /* pic16_popCopyReg - copy a pcode operator */
1478 /*-----------------------------------------------------------------*/
1479 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1483 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1484 pcor->pcop.type = pc->pcop.type;
1486 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1487 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1489 pcor->pcop.name = NULL;
1492 pcor->rIdx = pc->rIdx;
1495 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1500 /*-----------------------------------------------------------------*/
1501 /* pic16_popGetLit - asm operator to pcode operator conversion */
1502 /*-----------------------------------------------------------------*/
1503 pCodeOp *pic16_popGetLit(unsigned int lit)
1505 return pic16_newpCodeOpLit(lit);
1508 /*-----------------------------------------------------------------*/
1509 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1510 /*-----------------------------------------------------------------*/
1511 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1513 return pic16_newpCodeOpLit2(lit, arg2);
1517 /*-----------------------------------------------------------------*/
1518 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1519 /*-----------------------------------------------------------------*/
1520 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1522 return pic16_newpCodeOpImmd(name, offset,index, 0);
1526 /*-----------------------------------------------------------------*/
1527 /* pic16_popGet - asm operator to pcode operator conversion */
1528 /*-----------------------------------------------------------------*/
1529 pCodeOp *pic16_popGetWithString(char *str)
1535 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1539 pcop = pic16_newpCodeOp(str,PO_STR);
1544 /*-----------------------------------------------------------------*/
1545 /* pic16_popRegFromString - */
1546 /*-----------------------------------------------------------------*/
1547 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1550 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1551 pcop->type = PO_DIR;
1553 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1554 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1559 pcop->name = Safe_calloc(1,strlen(str)+1);
1560 strcpy(pcop->name,str);
1562 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1564 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1565 if(PCOR(pcop)->r == NULL) {
1566 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1567 // __FUNCTION__, __LINE__, str, size, offset);
1570 // PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1571 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1573 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1575 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d",__LINE__,pcop->name,size,offset);
1577 PCOR(pcop)->instance = offset;
1582 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1586 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1588 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1589 PCOR(pcop)->rIdx = rIdx;
1590 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1592 PCOR(pcop)->r->isFree = 0;
1593 PCOR(pcop)->r->wasUsed = 1;
1595 pcop->type = PCOR(pcop)->r->pc_type;
1600 /*---------------------------------------------------------------------------------*/
1601 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1603 /*---------------------------------------------------------------------------------*/
1604 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1609 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1611 /* comment the following check, so errors to throw up */
1612 // if(!pcop2)return NULL;
1614 temp = pic16_popGet(aop_dst, offset);
1615 pcop2->pcop2 = temp;
1622 /*--------------------------------------------------------------------------------.-*/
1623 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1624 /* VR 030601 , adapted by Hans Dorn */
1625 /*--------------------------------------------------------------------------------.-*/
1626 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1630 pcop2 = (pCodeOpReg2 *)src;
1638 /*---------------------------------------------------------------------------------*/
1639 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1640 /* movff instruction */
1641 /*---------------------------------------------------------------------------------*/
1642 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1647 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1648 pcop2->pcop2 = pic16_popCopyReg(dst);
1650 /* the pCodeOp may be already allocated */
1651 pcop2 = (pCodeOpReg2 *)(src);
1652 pcop2->pcop2 = (pCodeOp *)(dst);
1659 /*-----------------------------------------------------------------*/
1660 /* pic16_popGet - asm operator to pcode operator conversion */
1661 /*-----------------------------------------------------------------*/
1662 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1664 //char *s = buffer ;
1668 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1669 /* offset is greater than
1672 // if (offset > (aop->size - 1) &&
1673 // aop->type != AOP_LIT)
1674 // return NULL; //zero;
1676 /* depending on type */
1677 switch (aop->type) {
1683 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1684 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1691 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1692 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
1693 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1694 PCOR(pcop)->r->wasUsed = 1;
1695 PCOR(pcop)->r->isFree = 0;
1697 PCOR(pcop)->instance = offset;
1698 pcop->type = PCOR(pcop)->r->pc_type;
1702 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1703 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1707 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1709 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1711 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1713 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1714 PCOR(pcop)->rIdx = rIdx;
1715 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1716 PCOR(pcop)->r->wasUsed=1;
1717 PCOR(pcop)->r->isFree=0;
1719 PCOR(pcop)->instance = offset;
1720 pcop->type = PCOR(pcop)->r->pc_type;
1721 // rs = aop->aopu.aop_reg[offset]->name;
1722 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1726 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1727 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1733 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1734 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1738 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1740 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1742 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1743 // pcop->type = PO_GPR_REGISTER;
1744 PCOR(pcop)->rIdx = rIdx;
1745 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
1746 PCOR(pcop)->r->wasUsed=1;
1747 PCOR(pcop)->r->isFree=0;
1749 PCOR(pcop)->instance = offset;
1750 pcop->type = PCOR(pcop)->r->pc_type;
1751 rs = aop->aopu.aop_reg[offset]->name;
1752 DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1757 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1759 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1760 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1761 //if(PCOR(pcop)->r == NULL)
1762 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1766 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1767 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1770 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1771 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1774 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1775 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1776 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1777 pcop->type = PCOR(pcop)->r->pc_type;
1778 pcop->name = PCOR(pcop)->r->name;
1784 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1786 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1787 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1789 switch( aop->aopu.pcop->type ) {
1790 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1791 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1793 assert( 0 ); /* should never reach here */;
1796 PCOI(pcop)->offset = offset;
1801 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1802 "pic16_popGet got unsupported aop->type");
1805 /*-----------------------------------------------------------------*/
1806 /* pic16_aopPut - puts a string for a aop */
1807 /*-----------------------------------------------------------------*/
1808 void pic16_aopPut (asmop *aop, char *s, int offset)
1813 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1815 if (aop->size && offset > ( aop->size - 1)) {
1816 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1817 "pic16_aopPut got offset > aop->size");
1821 /* will assign value to value */
1822 /* depending on where it is ofcourse */
1823 switch (aop->type) {
1826 sprintf(d,"(%s + %d)",
1827 aop->aopu.aop_dir,offset);
1828 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1831 sprintf(d,"%s",aop->aopu.aop_dir);
1834 DEBUGpic16_emitcode(";","%d",__LINE__);
1836 pic16_emitcode("movf","%s,w",s);
1837 pic16_emitcode("movwf","%s",d);
1840 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1841 if(offset >= aop->size) {
1842 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1845 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1848 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1855 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1856 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1859 strcmp(s,"r0") == 0 ||
1860 strcmp(s,"r1") == 0 ||
1861 strcmp(s,"r2") == 0 ||
1862 strcmp(s,"r3") == 0 ||
1863 strcmp(s,"r4") == 0 ||
1864 strcmp(s,"r5") == 0 ||
1865 strcmp(s,"r6") == 0 ||
1866 strcmp(s,"r7") == 0 )
1867 pic16_emitcode("mov","%s,%s ; %d",
1868 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1872 if(strcmp(s,"W")==0 )
1873 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
1875 pic16_emitcode("movwf","%s",
1876 aop->aopu.aop_reg[offset]->name);
1878 if(strcmp(s,zero)==0) {
1879 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1881 } else if(strcmp(s,"W")==0) {
1882 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1883 pcop->type = PO_GPR_REGISTER;
1885 PCOR(pcop)->rIdx = -1;
1886 PCOR(pcop)->r = NULL;
1888 DEBUGpic16_emitcode(";","%d",__LINE__);
1889 pcop->name = Safe_strdup(s);
1890 pic16_emitpcode(POC_MOVFW,pcop);
1891 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1892 } else if(strcmp(s,one)==0) {
1893 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1894 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1896 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1904 if (aop->type == AOP_DPTR2)
1910 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1911 "pic16_aopPut writting to code space");
1915 while (offset > aop->coff) {
1917 pic16_emitcode ("inc","dptr");
1920 while (offset < aop->coff) {
1922 pic16_emitcode("lcall","__decdptr");
1927 /* if not in accumulater */
1930 pic16_emitcode ("movx","@dptr,a");
1932 if (aop->type == AOP_DPTR2)
1940 while (offset > aop->coff) {
1942 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1944 while (offset < aop->coff) {
1946 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1952 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1957 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1959 if (strcmp(s,"r0") == 0 ||
1960 strcmp(s,"r1") == 0 ||
1961 strcmp(s,"r2") == 0 ||
1962 strcmp(s,"r3") == 0 ||
1963 strcmp(s,"r4") == 0 ||
1964 strcmp(s,"r5") == 0 ||
1965 strcmp(s,"r6") == 0 ||
1966 strcmp(s,"r7") == 0 ) {
1968 sprintf(buffer,"a%s",s);
1969 pic16_emitcode("mov","@%s,%s",
1970 aop->aopu.aop_ptr->name,buffer);
1972 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1977 if (strcmp(s,"a") == 0)
1978 pic16_emitcode("push","acc");
1980 pic16_emitcode("push","%s",s);
1985 /* if bit variable */
1986 if (!aop->aopu.aop_dir) {
1987 pic16_emitcode("clr","a");
1988 pic16_emitcode("rlc","a");
1991 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1994 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1997 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1999 lbl = newiTempLabel(NULL);
2001 if (strcmp(s,"a")) {
2004 pic16_emitcode("clr","c");
2005 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2006 pic16_emitcode("cpl","c");
2007 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2008 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2015 if (strcmp(aop->aopu.aop_str[offset],s))
2016 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2021 if (!offset && (strcmp(s,"acc") == 0))
2024 if (strcmp(aop->aopu.aop_str[offset],s))
2025 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2029 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2030 "pic16_aopPut got unsupported aop->type");
2036 /*-----------------------------------------------------------------*/
2037 /* mov2w - generate either a MOVLW or MOVFW based operand type */
2038 /*-----------------------------------------------------------------*/
2039 static void mov2w (asmop *aop, int offset)
2045 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2048 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2050 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2055 /* push pcop into stack */
2056 void pic16_pushpCodeOp(pCodeOp *pcop)
2058 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2059 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2062 /* pop pcop from stack */
2063 void pic16_poppCodeOp(pCodeOp *pcop)
2065 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2069 /*-----------------------------------------------------------------*/
2070 /* pushw - pushes wreg to stack */
2071 /*-----------------------------------------------------------------*/
2074 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2075 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2079 /*-----------------------------------------------------------------*/
2080 /* pushaop - pushes aop to stack */
2081 /*-----------------------------------------------------------------*/
2082 void pushaop(asmop *aop, int offset)
2084 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2085 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2088 /*-----------------------------------------------------------------*/
2089 /* popaop - pops aop from stack */
2090 /*-----------------------------------------------------------------*/
2091 void popaop(asmop *aop, int offset)
2093 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2094 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2097 void popaopidx(asmop *aop, int offset, int index)
2101 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2103 if(STACK_MODEL_LARGE)ofs++;
2105 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2106 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2109 /*-----------------------------------------------------------------*/
2110 /* reAdjustPreg - points a register back to where it should */
2111 /*-----------------------------------------------------------------*/
2112 static void reAdjustPreg (asmop *aop)
2116 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2118 if ((size = aop->size) <= 1)
2121 switch (aop->type) {
2125 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2129 if (aop->type == AOP_DPTR2)
2135 pic16_emitcode("lcall","__decdptr");
2138 if (aop->type == AOP_DPTR2)
2150 /*-----------------------------------------------------------------*/
2151 /* opIsGptr: returns non-zero if the passed operand is */
2152 /* a generic pointer type. */
2153 /*-----------------------------------------------------------------*/
2154 static int opIsGptr(operand *op)
2156 sym_link *type = operandType(op);
2158 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2159 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2167 /*-----------------------------------------------------------------*/
2168 /* pic16_getDataSize - get the operand data size */
2169 /*-----------------------------------------------------------------*/
2170 int pic16_getDataSize(operand *op)
2172 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2175 return AOP_SIZE(op);
2177 // tsd- in the pic port, the genptr size is 1, so this code here
2178 // fails. ( in the 8051 port, the size was 4).
2181 size = AOP_SIZE(op);
2182 if (size == GPTRSIZE)
2184 sym_link *type = operandType(op);
2185 if (IS_GENPTR(type))
2187 /* generic pointer; arithmetic operations
2188 * should ignore the high byte (pointer type).
2191 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2198 /*-----------------------------------------------------------------*/
2199 /* pic16_outAcc - output Acc */
2200 /*-----------------------------------------------------------------*/
2201 void pic16_outAcc(operand *result)
2204 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2205 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2208 size = pic16_getDataSize(result);
2210 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2213 /* unsigned or positive */
2215 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2220 /*-----------------------------------------------------------------*/
2221 /* pic16_outBitC - output a bit C */
2222 /* Move to result the value of Carry flag -- VR */
2223 /*-----------------------------------------------------------------*/
2224 void pic16_outBitC(operand *result)
2228 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2229 /* if the result is bit */
2230 if (AOP_TYPE(result) == AOP_CRY) {
2231 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2232 pic16_aopPut(AOP(result),"c",0);
2235 i = AOP_SIZE(result);
2237 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2239 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2242 pic16_emitcode("clr","a ; %d", __LINE__);
2243 pic16_emitcode("rlc","a");
2244 pic16_outAcc(result);
2249 /*-----------------------------------------------------------------*/
2250 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2251 /*-----------------------------------------------------------------*/
2252 void pic16_toBoolean(operand *oper)
2254 int size = AOP_SIZE(oper) - 1;
2257 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2259 if ( AOP_TYPE(oper) != AOP_ACC) {
2260 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2263 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2268 #if !defined(GEN_Not)
2269 /*-----------------------------------------------------------------*/
2270 /* genNot - generate code for ! operation */
2271 /*-----------------------------------------------------------------*/
2272 static void pic16_genNot (iCode *ic)
2277 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2278 /* assign asmOps to operand & result */
2279 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2280 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2282 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2283 /* if in bit space then a special case */
2284 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2285 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2286 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2287 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2289 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2290 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2291 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2296 size = AOP_SIZE(IC_LEFT(ic));
2298 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2299 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2300 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2303 pic16_toBoolean(IC_LEFT(ic));
2305 tlbl = newiTempLabel(NULL);
2306 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2307 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2308 pic16_outBitC(IC_RESULT(ic));
2311 /* release the aops */
2312 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2313 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2318 #if !defined(GEN_Cpl)
2319 /*-----------------------------------------------------------------*/
2320 /* genCpl - generate code for complement */
2321 /*-----------------------------------------------------------------*/
2322 static void pic16_genCpl (iCode *ic)
2328 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2329 /* assign asmOps to operand & result */
2330 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2331 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2333 /* if both are in bit space then
2335 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2336 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2338 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2339 pic16_emitcode("cpl","c");
2340 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2344 size = AOP_SIZE(IC_RESULT(ic));
2347 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2349 pic16_emitcode("cpl","a");
2350 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2352 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2353 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2355 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2356 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2364 /* release the aops */
2365 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2366 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2370 /*-----------------------------------------------------------------*/
2371 /* genUminusFloat - unary minus for floating points */
2372 /*-----------------------------------------------------------------*/
2373 static void genUminusFloat(operand *op,operand *result)
2375 int size ,offset =0 ;
2378 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2379 /* for this we just need to flip the
2380 first it then copy the rest in place */
2381 size = AOP_SIZE(op) - 1;
2382 l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2386 pic16_emitcode("cpl","acc.7");
2387 pic16_aopPut(AOP(result),"a",3);
2390 pic16_aopPut(AOP(result),
2391 pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2397 /*-----------------------------------------------------------------*/
2398 /* genUminus - unary minus code generation */
2399 /*-----------------------------------------------------------------*/
2400 static void genUminus (iCode *ic)
2403 sym_link *optype, *rtype;
2405 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2408 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2409 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2411 /* if both in bit space then special case */
2412 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2413 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2415 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2416 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2417 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2422 optype = operandType(IC_LEFT(ic));
2423 rtype = operandType(IC_RESULT(ic));
2425 /* if float then do float stuff */
2426 if (IS_FLOAT(optype)) {
2427 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2431 /* otherwise subtract from zero by taking the 2's complement */
2432 size = AOP_SIZE(IC_LEFT(ic));
2434 for(i=0; i<size; i++) {
2435 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2436 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)),i));
2438 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2439 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2443 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2444 for(i=1; i<size; i++) {
2446 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2450 /* release the aops */
2451 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2452 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2455 /*-----------------------------------------------------------------*/
2456 /* saveRegisters - will look for a call and save the registers */
2457 /*-----------------------------------------------------------------*/
2458 static void saveRegisters(iCode *lic)
2465 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2467 for (ic = lic ; ic ; ic = ic->next)
2468 if (ic->op == CALL || ic->op == PCALL)
2472 fprintf(stderr,"found parameter push with no function call\n");
2476 /* if the registers have been saved already then
2478 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2481 /* find the registers in use at this time
2482 and push them away to safety */
2483 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2487 if (options.useXstack) {
2488 if (bitVectBitValue(rsave,R0_IDX))
2489 pic16_emitcode("mov","b,r0");
2490 pic16_emitcode("mov","r0,%s",spname);
2491 for (i = 0 ; i < pic16_nRegs ; i++) {
2492 if (bitVectBitValue(rsave,i)) {
2494 pic16_emitcode("mov","a,b");
2496 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2497 pic16_emitcode("movx","@r0,a");
2498 pic16_emitcode("inc","r0");
2501 pic16_emitcode("mov","%s,r0",spname);
2502 if (bitVectBitValue(rsave,R0_IDX))
2503 pic16_emitcode("mov","r0,b");
2505 //for (i = 0 ; i < pic16_nRegs ; i++) {
2506 // if (bitVectBitValue(rsave,i))
2507 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2510 dtype = operandType(IC_LEFT(ic));
2511 if (currFunc && dtype &&
2512 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2513 IFFUNC_ISISR(currFunc->type) &&
2516 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2519 /*-----------------------------------------------------------------*/
2520 /* unsaveRegisters - pop the pushed registers */
2521 /*-----------------------------------------------------------------*/
2522 static void unsaveRegisters (iCode *ic)
2527 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2528 /* find the registers in use at this time
2529 and push them away to safety */
2530 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2533 if (options.useXstack) {
2534 pic16_emitcode("mov","r0,%s",spname);
2535 for (i = pic16_nRegs ; i >= 0 ; i--) {
2536 if (bitVectBitValue(rsave,i)) {
2537 pic16_emitcode("dec","r0");
2538 pic16_emitcode("movx","a,@r0");
2540 pic16_emitcode("mov","b,a");
2542 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2546 pic16_emitcode("mov","%s,r0",spname);
2547 if (bitVectBitValue(rsave,R0_IDX))
2548 pic16_emitcode("mov","r0,b");
2550 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2551 // if (bitVectBitValue(rsave,i))
2552 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2558 /*-----------------------------------------------------------------*/
2560 /*-----------------------------------------------------------------*/
2561 static void pushSide(operand * oper, int size)
2564 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2566 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2567 if (AOP_TYPE(oper) != AOP_REG &&
2568 AOP_TYPE(oper) != AOP_DIR &&
2570 pic16_emitcode("mov","a,%s",l);
2571 pic16_emitcode("push","acc");
2573 pic16_emitcode("push","%s",l);
2578 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2580 // (AOP(left)->aopu.pcop->type == PO_DIR)?
2582 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2583 pic16_emitpcode(POC_MOVFW, src);
2584 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2586 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2587 src, pic16_popGet(AOP(op), offset)));
2592 /*-----------------------------------------------------------------*/
2593 /* assignResultValue - assign results to oper, rescall==1 is */
2594 /* called from genCall() or genPCall() */
2595 /*-----------------------------------------------------------------*/
2596 static void assignResultValue(operand * oper, int rescall)
2598 int size = AOP_SIZE(oper);
2600 DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2601 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2604 /* assign result from a call/pcall function() */
2606 /* function results are stored in a special order,
2607 * see top of file with Function return policy, or manual */
2610 /* 8-bits, result in WREG */
2611 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2614 /* 16-bits, result in PRODL:WREG */
2615 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2619 /* 24-bits, result in PRODH:PRODL:WREG */
2620 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2624 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2625 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2628 /* >32-bits, result on stack, and FSR0 points to beginning.
2629 * Fix stack when done */
2632 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2633 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2635 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2640 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2641 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2642 if(STACK_MODEL_LARGE) {
2644 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2648 if(!GpsuedoStkPtr) {
2649 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2650 /* The last byte in the assignment is in W */
2652 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2657 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2658 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2660 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2666 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2668 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2678 /*-----------------------------------------------------------------*/
2679 /* genIpush - genrate code for pushing this gets a little complex */
2680 /*-----------------------------------------------------------------*/
2681 static void genIpush (iCode *ic)
2685 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2688 pic16_aopOp(IC_LEFT(ic), ic, FALSE);
2691 size = AOP_SIZE( IC_LEFT(ic) );
2694 mov2w( AOP(IC_LEFT(ic)), offset );
2700 int size, offset = 0 ;
2704 /* if this is not a parm push : ie. it is spill push
2705 and spill push is always done on the local stack */
2706 if (!ic->parmPush) {
2708 /* and the item is spilt then do nothing */
2709 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2712 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2713 size = AOP_SIZE(IC_LEFT(ic));
2714 /* push it on the stack */
2716 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2721 pic16_emitcode("push","%s",l);
2726 /* this is a paramter push: in this case we call
2727 the routine to find the call and save those
2728 registers that need to be saved */
2731 /* then do the push */
2732 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2735 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2736 size = AOP_SIZE(IC_LEFT(ic));
2739 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2740 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2741 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2743 pic16_emitcode("mov","a,%s",l);
2744 pic16_emitcode("push","acc");
2746 pic16_emitcode("push","%s",l);
2749 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2753 /*-----------------------------------------------------------------*/
2754 /* genIpop - recover the registers: can happen only for spilling */
2755 /*-----------------------------------------------------------------*/
2756 static void genIpop (iCode *ic)
2758 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2763 /* if the temp was not pushed then */
2764 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2767 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2768 size = AOP_SIZE(IC_LEFT(ic));
2771 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2774 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2778 /*-----------------------------------------------------------------*/
2779 /* unsaverbank - restores the resgister bank from stack */
2780 /*-----------------------------------------------------------------*/
2781 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2783 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2789 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2791 if (options.useXstack) {
2793 r = getFreePtr(ic,&aop,FALSE);
2796 pic16_emitcode("mov","%s,_spx",r->name);
2797 pic16_emitcode("movx","a,@%s",r->name);
2798 pic16_emitcode("mov","psw,a");
2799 pic16_emitcode("dec","%s",r->name);
2802 pic16_emitcode ("pop","psw");
2805 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2806 if (options.useXstack) {
2807 pic16_emitcode("movx","a,@%s",r->name);
2808 //pic16_emitcode("mov","(%s+%d),a",
2809 // regspic16[i].base,8*bank+regspic16[i].offset);
2810 pic16_emitcode("dec","%s",r->name);
2813 pic16_emitcode("pop",""); //"(%s+%d)",
2814 //regspic16[i].base,8*bank); //+regspic16[i].offset);
2817 if (options.useXstack) {
2819 pic16_emitcode("mov","_spx,%s",r->name);
2820 pic16_freeAsmop(NULL,aop,ic,TRUE);
2826 /*-----------------------------------------------------------------*/
2827 /* saverbank - saves an entire register bank on the stack */
2828 /*-----------------------------------------------------------------*/
2829 static void saverbank (int bank, iCode *ic, bool pushPsw)
2831 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2837 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2838 if (options.useXstack) {
2841 r = getFreePtr(ic,&aop,FALSE);
2842 pic16_emitcode("mov","%s,_spx",r->name);
2846 for (i = 0 ; i < pic16_nRegs ;i++) {
2847 if (options.useXstack) {
2848 pic16_emitcode("inc","%s",r->name);
2849 //pic16_emitcode("mov","a,(%s+%d)",
2850 // regspic16[i].base,8*bank+regspic16[i].offset);
2851 pic16_emitcode("movx","@%s,a",r->name);
2853 pic16_emitcode("push","");// "(%s+%d)",
2854 //regspic16[i].base,8*bank+regspic16[i].offset);
2858 if (options.useXstack) {
2859 pic16_emitcode("mov","a,psw");
2860 pic16_emitcode("movx","@%s,a",r->name);
2861 pic16_emitcode("inc","%s",r->name);
2862 pic16_emitcode("mov","_spx,%s",r->name);
2863 pic16_freeAsmop (NULL,aop,ic,TRUE);
2866 pic16_emitcode("push","psw");
2868 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2876 /*-----------------------------------------------------------------*/
2877 /* genCall - generates a call statement */
2878 /*-----------------------------------------------------------------*/
2879 static void genCall (iCode *ic)
2884 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2886 /* if caller saves & we have not saved then */
2890 /* if we are calling a function that is not using
2891 * the same register bank then we need to save the
2892 * destination registers on the stack */
2893 dtype = operandType(IC_LEFT(ic));
2894 if (currFunc && dtype &&
2895 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2896 IFFUNC_ISISR(currFunc->type) &&
2899 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2902 /* initialise stackParms for IPUSH pushes */
2903 // stackParms = psuedoStkPtr;
2904 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2906 /* if send set is not empty the assign */
2910 /* For the Pic port, there is no data stack.
2911 * So parameters passed to functions are stored
2912 * in registers. (The pCode optimizer will get
2913 * rid of most of these :). */
2915 int psuedoStkPtr=-1;
2916 int firstTimeThruLoop = 1;
2918 _G.sendSet = reverseSet(_G.sendSet);
2920 /* First figure how many parameters are getting passed */
2921 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2922 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2923 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2924 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2927 stackParms = psuedoStkPtr;
2929 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2930 int size, offset = 0;
2932 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2933 size = AOP_SIZE(IC_LEFT(sic));
2936 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2937 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2938 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2940 if(!firstTimeThruLoop) {
2941 /* If this is not the first time we've been through the loop
2942 * then we need to save the parameter in a temporary
2943 * register. The last byte of the last parameter is
2947 --psuedoStkPtr; // sanity check
2950 firstTimeThruLoop=0;
2952 mov2w (AOP(IC_LEFT(sic)), offset);
2955 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2961 pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2962 OP_SYMBOL(IC_LEFT(ic))->rname :
2963 OP_SYMBOL(IC_LEFT(ic))->name));
2966 /* if we need assign a result value */
2967 if ((IS_ITEMP(IC_RESULT(ic)) &&
2968 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2969 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2970 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2973 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2976 assignResultValue(IC_RESULT(ic), 1);
2978 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2979 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2981 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2984 if(!stackParms && ic->parmBytes) {
2985 stackParms = ic->parmBytes;
2989 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2990 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2991 if(STACK_MODEL_LARGE) {
2993 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2997 /* adjust the stack for parameters if required */
2998 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3000 if (ic->parmBytes) {
3003 if (ic->parmBytes > 3) {
3004 pic16_emitcode("mov","a,%s",spname);
3005 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3006 pic16_emitcode("mov","%s,a",spname);
3008 for ( i = 0 ; i < ic->parmBytes ;i++)
3009 pic16_emitcode("dec","%s",spname);
3014 /* if register bank was saved then pop them */
3016 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3018 /* if we hade saved some registers then unsave them */
3019 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3020 unsaveRegisters (ic);
3026 /*-----------------------------------------------------------------*/ // patch 14
3027 /* genPcall - generates a call by pointer statement */
3028 /*-----------------------------------------------------------------*/
3030 // new version, created from genCall
3032 static void genPcall (iCode *ic)
3036 symbol *retlbl = newiTempLabel(NULL);
3037 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3039 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3041 /* if caller saves & we have not saved then */
3045 /* if we are calling a function that is not using
3046 * the same register bank then we need to save the
3047 * destination registers on the stack */
3048 dtype = operandType(IC_LEFT(ic));
3049 if (currFunc && dtype &&
3050 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
3051 IFFUNC_ISISR(currFunc->type) &&
3054 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3056 /* if send set is not empty the assign */
3060 /* For the Pic port, there is no data stack.
3061 * So parameters passed to functions are stored
3062 * in registers. (The pCode optimizer will get
3063 * rid of most of these :). */
3065 int psuedoStkPtr=-1;
3066 int firstTimeThruLoop = 1;
3068 _G.sendSet = reverseSet(_G.sendSet);
3070 /* First figure how many parameters are getting passed */
3071 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3072 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3073 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
3074 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
3077 stackParms = psuedoStkPtr;
3079 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3080 int size, offset = 0;
3082 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3083 size = AOP_SIZE(IC_LEFT(sic));
3086 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3087 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3088 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3090 if(!firstTimeThruLoop) {
3091 /* If this is not the first time we've been through the loop
3092 * then we need to save the parameter in a temporary
3093 * register. The last byte of the last parameter is
3097 --psuedoStkPtr; // sanity check
3100 firstTimeThruLoop=0;
3102 mov2w (AOP(IC_LEFT(sic)), offset);
3105 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3110 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3112 // push return address
3113 // push $ on return stack, then replace with retlbl
3115 pic16_emitpcodeNULLop(POC_PUSH);
3117 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3118 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3119 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3120 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3121 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3122 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3124 /* make the call by writing the pointer into pc */
3125 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3126 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3128 // note: MOVFF to PCL not allowed
3129 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3130 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3133 // pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key));
3134 // pic16_emitpcodeNULLop(POC_NOP);
3135 // pic16_emitpcodeNULLop(POC_NOP);
3137 /* return address is here: (X) */
3138 pic16_emitpLabelFORCE(retlbl->key);
3140 // pic16_emitpcodeNULLop(POC_NOP);
3142 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3145 /* if we need assign a result value */
3146 if ((IS_ITEMP(IC_RESULT(ic)) &&
3147 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3148 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
3149 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3152 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3155 assignResultValue(IC_RESULT(ic), 1);
3157 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3158 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3160 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3164 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3165 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3166 if(STACK_MODEL_LARGE) {
3168 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3172 /* adjust the stack for parameters if required */
3173 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3175 if (ic->parmBytes) {
3178 if (ic->parmBytes > 3) {
3179 pic16_emitcode("mov","a,%s",spname);
3180 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3181 pic16_emitcode("mov","%s,a",spname);
3183 for ( i = 0 ; i < ic->parmBytes ;i++)
3184 pic16_emitcode("dec","%s",spname);
3187 /* if register bank was saved then pop them */
3189 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3191 /* if we hade saved some registers then unsave them */
3192 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3193 unsaveRegisters (ic);
3198 // old version, kept for reference
3200 /*-----------------------------------------------------------------*/
3201 /* genPcall - generates a call by pointer statement */
3202 /*-----------------------------------------------------------------*/
3203 static void genPcall (iCode *ic)
3206 symbol *rlbl = newiTempLabel(NULL);
3209 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3210 /* if caller saves & we have not saved then */
3214 /* if we are calling a function that is not using
3215 the same register bank then we need to save the
3216 destination registers on the stack */
3217 dtype = operandType(IC_LEFT(ic));
3218 if (currFunc && dtype &&
3219 IFFUNC_ISISR(currFunc->type) &&
3220 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3221 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3224 /* push the return address on to the stack */
3225 pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3226 pic16_emitcode("push","acc");
3227 pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3228 pic16_emitcode("push","acc");
3230 if (options.model == MODEL_FLAT24)
3232 pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3233 pic16_emitcode("push","acc");
3236 /* now push the calling address */
3237 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3239 pushSide(IC_LEFT(ic), FPTRSIZE);
3241 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3243 /* if send set is not empty the assign */
3247 for (sic = setFirstItem(_G.sendSet) ; sic ;
3248 sic = setNextItem(_G.sendSet)) {
3249 int size, offset = 0;
3250 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3251 size = AOP_SIZE(IC_LEFT(sic));
3253 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3255 if (strcmp(l,fReturn[offset]))
3256 pic16_emitcode("mov","%s,%s",
3261 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3266 pic16_emitcode("ret","");
3267 pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3270 /* if we need assign a result value */
3271 if ((IS_ITEMP(IC_RESULT(ic)) &&
3272 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3273 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3274 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3277 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3280 assignResultValue(IC_RESULT(ic), 1);
3282 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3285 /* adjust the stack for parameters if
3287 if (ic->parmBytes) {
3289 if (ic->parmBytes > 3) {
3290 pic16_emitcode("mov","a,%s",spname);
3291 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3292 pic16_emitcode("mov","%s,a",spname);
3294 for ( i = 0 ; i < ic->parmBytes ;i++)
3295 pic16_emitcode("dec","%s",spname);
3299 /* if register bank was saved then unsave them */
3300 if (currFunc && dtype &&
3301 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3302 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3304 /* if we hade saved some registers then
3307 unsaveRegisters (ic);
3313 /*-----------------------------------------------------------------*/
3314 /* resultRemat - result is rematerializable */
3315 /*-----------------------------------------------------------------*/
3316 static int resultRemat (iCode *ic)
3318 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3319 if (SKIP_IC(ic) || ic->op == IFX)
3322 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3323 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3324 if (sym->remat && !POINTER_SET(ic))
3331 #if defined(__BORLANDC__) || defined(_MSC_VER)
3332 #define STRCASECMP stricmp
3334 #define STRCASECMP strcasecmp
3338 /*-----------------------------------------------------------------*/
3339 /* inExcludeList - return 1 if the string is in exclude Reg list */
3340 /*-----------------------------------------------------------------*/
3341 static bool inExcludeList(char *s)
3343 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3346 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3347 if (options.excludeRegs[i] &&
3348 STRCASECMP(options.excludeRegs[i],"none") == 0)
3351 for ( i = 0 ; options.excludeRegs[i]; i++) {
3352 if (options.excludeRegs[i] &&
3353 STRCASECMP(s,options.excludeRegs[i]) == 0)
3360 /*-----------------------------------------------------------------*/
3361 /* genFunction - generated code for function entry */
3362 /*-----------------------------------------------------------------*/
3363 static void genFunction (iCode *ic)
3368 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3370 pic16_labelOffset += (max_key+4);
3375 ftype = operandType(IC_LEFT(ic));
3376 sym = OP_SYMBOL(IC_LEFT(ic));
3378 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3379 /* create an absolute section at the interrupt vector:
3380 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3388 sym = OP_SYMBOL( IC_LEFT(ic));
3390 if(interrupts[i]->name
3391 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3398 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3399 __FILE__, __LINE__, sym->name);
3402 _G.interruptvector = found;
3405 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3406 asym = newSymbol(asymname, 0);
3408 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3409 pic16_addpBlock( apb );
3411 pic16_addpCode2pBlock(apb,
3412 pic16_newpCodeCharP(";-----------------------------------------"));
3415 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3417 pic16_addpCode2pBlock(apb,
3418 pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3420 /* mark the end of this tiny function */
3421 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3426 abSym = Safe_calloc(1, sizeof(absSym));
3427 abSym->name = Safe_strdup( asymname );
3429 switch( _G.interruptvector ) {
3430 case 0: abSym->address = 0x000000; break;
3431 case 1: abSym->address = 0x000008; break;
3432 case 2: abSym->address = 0x000018; break;
3435 /* relocate interrupt vectors if needed */
3436 abSym->address += pic16_options.ivt_loc;
3438 addSet(&absSymSet, abSym);
3443 /* create the function header */
3444 pic16_emitcode(";","-----------------------------------------");
3445 pic16_emitcode(";"," function %s",sym->name);
3446 pic16_emitcode(";","-----------------------------------------");
3448 pic16_emitcode("","%s:",sym->rname);
3449 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3455 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3456 if(!strcmp(ab->name, sym->name)) {
3457 pic16_pBlockConvert2Absolute(pb);
3464 if(IFFUNC_ISNAKED(ftype)) {
3465 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3469 /* if critical function then turn interrupts off */
3470 if (IFFUNC_ISCRITICAL(ftype))
3471 pic16_emitcode("clr","ea");
3473 /* if this is an interrupt service routine then
3474 * save acc, b, dpl, dph */
3475 if (IFFUNC_ISISR(sym->type)) {
3478 _G.usefastretfie = 1; /* use shadow registers by default */
3479 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3480 if(!(_G.interruptvector == 1)) {
3482 /* do not save WREG,STATUS,BSR for high priority interrupts
3483 * because they are stored in the hardware shadow registers already */
3484 _G.usefastretfie = 0;
3485 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3486 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3487 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3491 /* these should really be optimized somehow, because not all
3492 * interrupt handlers modify them */
3493 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3494 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3495 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3496 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3498 // pic16_pBlockConvert2ISR(pb);
3500 /* if any registers used */
3501 if (sym->regsUsed) {
3502 /* save the registers used */
3503 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3504 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3505 if (bitVectBitValue(sym->regsUsed,i)) {
3507 fprintf(stderr, "%s:%d function %s uses register %s\n",
3508 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3509 pic16_regWithIdx(i)->name);
3512 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3515 if(!pic16_regWithIdx(i)->wasUsed) {
3516 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3517 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3519 pic16_regWithIdx(i)->wasUsed = 1;
3525 /* emit code to setup stack frame if user enabled,
3526 * and function is not main() */
3528 // fprintf(stderr, "function name: %s\n", sym->name);
3529 if(strcmp(sym->name, "main")) {
3530 if(/*!options.ommitFramePtr || */sym->regsUsed) {
3531 /* setup the stack frame */
3532 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3533 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3534 if(STACK_MODEL_LARGE)
3535 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3539 /* if callee-save to be used for this function
3540 * then save the registers being used in this function */
3541 // if (IFFUNC_CALLEESAVES(sym->type))
3545 // fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3547 // pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3549 /* if any registers used */
3550 if (sym->regsUsed) {
3551 /* save the registers used */
3552 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3553 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3554 if (bitVectBitValue(sym->regsUsed,i)) {
3557 fprintf(stderr, "%s:%d function %s uses register %s (wasUsed: %d, %p)\n",
3558 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3559 pic16_regWithIdx(i)->name,
3560 pic16_regWithIdx(i)->wasUsed,
3561 pic16_regWithIdx(i));
3564 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3566 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3567 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3568 // &pic16_pc_postdec1, 0));
3572 if(!pic16_regWithIdx(i)->wasUsed) {
3573 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3574 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3576 pic16_regWithIdx(i)->wasUsed = 1;
3588 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3590 if (options.useXstack) {
3591 pic16_emitcode("mov","r0,%s",spname);
3592 pic16_emitcode("mov","a,_bp");
3593 pic16_emitcode("movx","@r0,a");
3594 pic16_emitcode("inc","%s",spname);
3596 /* set up the stack */
3597 pic16_emitcode ("push","_bp"); /* save the callers stack */
3599 pic16_emitcode ("mov","_bp,%s",spname);
3602 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3604 /* adjust the stack for the function */
3609 werror(W_STACK_OVERFLOW,sym->name);
3611 if (i > 3 && sym->recvSize < 4) {
3612 pic16_emitcode ("mov","a,sp");
3613 pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3614 pic16_emitcode ("mov","sp,a");
3617 pic16_emitcode("inc","sp");
3621 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3623 pic16_emitcode ("mov","a,_spx");
3624 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3625 pic16_emitcode ("mov","_spx,a");
3630 /*-----------------------------------------------------------------*/
3631 /* genEndFunction - generates epilogue for functions */
3632 /*-----------------------------------------------------------------*/
3633 static void genEndFunction (iCode *ic)
3635 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3637 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3639 if(IFFUNC_ISNAKED(sym->type)) {
3640 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3644 /* add code for ISCRITICAL */
3647 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3649 pic16_emitcode ("mov","%s,_bp",spname);
3653 /* if use external stack but some variables were
3654 added to the local stack then decrement the
3656 if (options.useXstack && sym->stack) {
3657 pic16_emitcode("mov","a,sp");
3658 pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3659 pic16_emitcode("mov","sp,a");
3664 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3665 if (options.useXstack) {
3666 pic16_emitcode("mov","r0,%s",spname);
3667 pic16_emitcode("movx","a,@r0");
3668 pic16_emitcode("mov","_bp,a");
3669 pic16_emitcode("dec","%s",spname);
3673 pic16_emitcode ("pop","_bp");
3678 if (IFFUNC_ISISR(sym->type)) {
3679 /* now we need to restore the registers */
3680 /* if any registers used */
3681 if (sym->regsUsed) {
3684 /* restore registers used */
3685 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3686 for ( i = sym->regsUsed->size; i >= 0; i--) {
3687 if (bitVectBitValue(sym->regsUsed,i)) {
3689 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3690 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3691 // pic16_regWithIdx(i)->name);
3693 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3695 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3696 // &pic16_pc_preinc1,
3697 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3703 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3704 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3705 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3706 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3708 if(!(_G.interruptvector == 1)) {
3709 /* do not restore interrupt vector for WREG,STATUS,BSR
3710 * for high priority interrupt, see genFunction */
3712 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3713 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3714 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3717 _G.interruptvector = 0; /* sanity check */
3719 // pic16_pBlockConvert2ISR(pb);
3722 /* if debug then send end of function */
3723 /* if (options.debug && currFunc) */
3725 debugFile->writeEndFunction (currFunc, ic, 1);
3728 if(_G.usefastretfie)
3729 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3731 pic16_emitpcodeNULLop(POC_RETFIE);
3732 _G.usefastretfie = 0;
3734 if (IFFUNC_ISCRITICAL(sym->type))
3735 pic16_emitcode("setb","ea");
3738 // pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3740 /* if any registers used */
3741 if (sym->regsUsed) {
3743 /* save the registers used */
3744 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3745 for ( i = sym->regsUsed->size; i >= 0; i--) {
3746 if (bitVectBitValue(sym->regsUsed,i)) {
3748 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3749 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3750 // pic16_regWithIdx(i)->name);
3752 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3754 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3755 // &pic16_pc_preinc1,
3756 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3763 // pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3764 /* if debug then send end of function */
3766 debugFile->writeEndFunction (currFunc, ic, 1);
3769 /* insert code to restore stack frame, if user enabled it
3770 * and function is not main() */
3773 if(strcmp(sym->name, "main")) {
3774 if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3775 /* restore stack frame */
3776 if(STACK_MODEL_LARGE)
3777 pic16_emitpcode(POC_MOVFF,
3778 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3779 pic16_emitpcode(POC_MOVFF,
3780 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3784 pic16_emitpcodeNULLop(POC_RETURN);
3786 /* Mark the end of a function */
3787 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3793 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3797 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3799 if(dest->type != PO_WREG)
3800 pic16_emitpcode(POC_MOVWF, dest);
3802 if(dest->type == PO_WREG && (offset == 0)) {
3803 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3807 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3808 pic16_popGet(AOP(op), offset), dest));
3812 /*-----------------------------------------------------------------*/
3813 /* genRet - generate code for return statement */
3814 /*-----------------------------------------------------------------*/
3815 static void genRet (iCode *ic)
3820 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3821 /* if we have no return value then
3822 * just generate the "ret" */
3827 /* we have something to return then
3828 * move the return value into place */
3829 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3830 size = AOP_SIZE(IC_LEFT(ic));
3834 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3835 // pic16_emitpcode(POC_MOVFF,
3836 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3839 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3840 // pic16_emitpcode(POC_MOVFF,
3841 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3844 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3845 // pic16_emitpcode(POC_MOVFF,
3846 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3849 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3851 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3852 // pic16_emitpcode(POC_MOVFF,
3853 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3856 /* >32-bits, setup stack and FSR0 */
3858 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3859 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3861 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3863 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3868 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3869 pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3871 if(STACK_MODEL_LARGE) {
3872 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3873 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3875 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3880 /* old code, left here for reference -- VR */
3884 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3886 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3887 pic16_emitpcomment("push %s",l);
3890 DEBUGpic16_emitcode(";", "%d", __LINE__);
3891 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3892 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3894 if (strcmp(fReturn[offset],l)) {
3895 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3896 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3897 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3899 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3903 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3913 if (strcmp(fReturn[pushed],"a"))
3914 pic16_emitcode("pop",fReturn[pushed]);
3916 pic16_emitcode("pop","acc");
3922 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3925 /* generate a jump to the return label
3926 * if the next is not the return statement */
3927 if (!(ic->next && ic->next->op == LABEL
3928 && IC_LABEL(ic->next) == returnLabel)) {
3930 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3931 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3935 /*-----------------------------------------------------------------*/
3936 /* genLabel - generates a label */
3937 /*-----------------------------------------------------------------*/
3938 static void genLabel (iCode *ic)
3942 /* special case never generate */
3943 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3944 if (IC_LABEL(ic) == entryLabel)
3947 pic16_emitpLabel(IC_LABEL(ic)->key);
3948 pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3951 /*-----------------------------------------------------------------*/
3952 /* genGoto - generates a goto */
3953 /*-----------------------------------------------------------------*/
3955 static void genGoto (iCode *ic)
3957 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3958 pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3962 /*-----------------------------------------------------------------*/
3963 /* genMultbits :- multiplication of bits */
3964 /*-----------------------------------------------------------------*/
3965 static void genMultbits (operand *left,
3969 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3971 if(!pic16_sameRegs(AOP(result),AOP(right)))
3972 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3974 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3975 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3976 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3981 /*-----------------------------------------------------------------*/
3982 /* genMultOneByte : 8 bit multiplication & division */
3983 /*-----------------------------------------------------------------*/
3984 static void genMultOneByte (operand *left,
3989 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3990 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3991 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3993 /* (if two literals, the value is computed before) */
3994 /* if one literal, literal on the right */
3995 if (AOP_TYPE(left) == AOP_LIT){
4001 /* size is already checked in genMult == 1 */
4002 // size = AOP_SIZE(result);
4004 if (AOP_TYPE(right) == AOP_LIT){
4005 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4006 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4007 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4008 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4010 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4011 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4012 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4013 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4016 pic16_genMult8X8_8 (left, right,result);
4019 /*-----------------------------------------------------------------*/
4020 /* genMultOneWord : 16 bit multiplication */
4021 /*-----------------------------------------------------------------*/
4022 static void genMultOneWord (operand *left,
4027 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4028 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4029 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4031 /* (if two literals, the value is computed before)
4032 * if one literal, literal on the right */
4033 if (AOP_TYPE(left) == AOP_LIT){
4039 /* size is checked already == 2 */
4040 // size = AOP_SIZE(result);
4042 if (AOP_TYPE(right) == AOP_LIT) {
4043 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4044 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4045 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4046 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4048 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4049 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4050 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4051 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4054 pic16_genMult16X16_16(left, right,result);
4057 /*-----------------------------------------------------------------*/
4058 /* genMultOneLong : 32 bit multiplication */
4059 /*-----------------------------------------------------------------*/
4060 static void genMultOneLong (operand *left,
4065 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4066 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4067 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4069 /* (if two literals, the value is computed before)
4070 * if one literal, literal on the right */
4071 if (AOP_TYPE(left) == AOP_LIT){
4077 /* size is checked already == 4 */
4078 // size = AOP_SIZE(result);
4080 if (AOP_TYPE(right) == AOP_LIT) {
4081 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4082 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4083 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4084 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4086 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4087 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4088 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4089 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4092 pic16_genMult32X32_32(left, right,result);
4097 /*-----------------------------------------------------------------*/
4098 /* genMult - generates code for multiplication */
4099 /*-----------------------------------------------------------------*/
4100 static void genMult (iCode *ic)
4102 operand *left = IC_LEFT(ic);
4103 operand *right = IC_RIGHT(ic);
4104 operand *result= IC_RESULT(ic);
4106 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4107 /* assign the amsops */
4108 pic16_aopOp (left,ic,FALSE);
4109 pic16_aopOp (right,ic,FALSE);
4110 pic16_aopOp (result,ic,TRUE);
4112 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4114 /* special cases first *
4116 if (AOP_TYPE(left) == AOP_CRY
4117 && AOP_TYPE(right)== AOP_CRY) {
4118 genMultbits(left,right,result);
4122 /* if both are of size == 1 */
4123 if(AOP_SIZE(left) == 1
4124 && AOP_SIZE(right) == 1) {
4125 genMultOneByte(left,right,result);
4129 /* if both are of size == 2 */
4130 if(AOP_SIZE(left) == 2
4131 && AOP_SIZE(right) == 2) {
4132 genMultOneWord(left, right, result);
4136 /* if both are of size == 4 */
4137 if(AOP_SIZE(left) == 4
4138 && AOP_SIZE(right) == 4) {
4139 genMultOneLong(left, right, result);
4143 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4146 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4147 /* should have been converted to function call */
4151 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4152 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4153 pic16_freeAsmop(result,NULL,ic,TRUE);
4156 /*-----------------------------------------------------------------*/
4157 /* genDivbits :- division of bits */
4158 /*-----------------------------------------------------------------*/
4159 static void genDivbits (operand *left,
4166 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4167 /* the result must be bit */
4168 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4169 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4173 pic16_emitcode("div","ab");
4174 pic16_emitcode("rrc","a");
4175 pic16_aopPut(AOP(result),"c",0);
4178 /*-----------------------------------------------------------------*/
4179 /* genDivOneByte : 8 bit division */
4180 /*-----------------------------------------------------------------*/
4181 static void genDivOneByte (operand *left,
4185 sym_link *opetype = operandType(result);
4190 /* result = divident / divisor
4191 * - divident may be a register or a literal,
4192 * - divisor may be a register or a literal,
4193 * so there are 3 cases (literal / literal is optimized
4194 * by the front-end) to handle.
4195 * In addition we must handle signed and unsigned, which
4196 * result in 6 final different cases -- VR */
4198 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4199 size = AOP_SIZE(result) - 1;
4201 /* signed or unsigned */
4202 if (SPEC_USIGN(opetype)) {
4203 pCodeOp *pct1, /* count */
4206 symbol *label1, *label2, *label3;;
4209 /* unsigned is easy */
4211 pct1 = pic16_popGetTempReg();
4212 pct2 = pic16_popGetTempReg();
4213 pct3 = pic16_popGetTempReg();
4215 label1 = newiTempLabel(NULL);
4216 label2 = newiTempLabel(NULL);
4217 label3 = newiTempLabel(NULL);
4219 /* the following algorithm is extracted from divuint.c */
4221 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4222 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4224 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4226 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4228 pic16_emitpLabel(label1->key);
4231 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4235 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4239 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4241 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4242 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4244 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4245 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4246 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4248 pic16_emitpLabel( label3->key );
4249 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4250 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4254 pic16_emitpLabel(label2->key);
4255 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4256 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4257 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4259 /* result is in wreg */
4260 if(AOP_TYPE(result) != AOP_ACC)
4261 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4263 pic16_popReleaseTempReg( pct3 );
4264 pic16_popReleaseTempReg( pct2 );
4265 pic16_popReleaseTempReg( pct1 );
4270 /* signed is a little bit more difficult */
4272 /* save the signs of the operands */
4273 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4275 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4276 pic16_emitcode("push","acc"); /* save it on the stack */
4278 /* now sign adjust for both left & right */
4279 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4281 lbl = newiTempLabel(NULL);
4282 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4283 pic16_emitcode("cpl","a");
4284 pic16_emitcode("inc","a");
4285 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4286 pic16_emitcode("mov","b,a");
4288 /* sign adjust left side */
4289 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4292 lbl = newiTempLabel(NULL);
4293 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4294 pic16_emitcode("cpl","a");
4295 pic16_emitcode("inc","a");
4296 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4298 /* now the division */
4299 pic16_emitcode("div","ab");
4300 /* we are interested in the lower order
4302 pic16_emitcode("mov","b,a");
4303 lbl = newiTempLabel(NULL);
4304 pic16_emitcode("pop","acc");
4305 /* if there was an over flow we don't
4306 adjust the sign of the result */
4307 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4308 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4310 pic16_emitcode("clr","a");
4311 pic16_emitcode("subb","a,b");
4312 pic16_emitcode("mov","b,a");
4313 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4315 /* now we are done */
4316 pic16_aopPut(AOP(result),"b",0);
4318 pic16_emitcode("mov","c,b.7");
4319 pic16_emitcode("subb","a,acc");
4322 pic16_aopPut(AOP(result),"a",offset++);
4326 /*-----------------------------------------------------------------*/
4327 /* genDiv - generates code for division */
4328 /*-----------------------------------------------------------------*/
4329 static void genDiv (iCode *ic)
4331 operand *left = IC_LEFT(ic);
4332 operand *right = IC_RIGHT(ic);
4333 operand *result= IC_RESULT(ic);
4336 /* Division is a very lengthy algorithm, so it is better
4337 * to call support routines than inlining algorithm.
4338 * Division functions written here just in case someone
4339 * wants to inline and not use the support libraries -- VR */
4341 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4342 /* assign the amsops */
4343 pic16_aopOp (left,ic,FALSE);
4344 pic16_aopOp (right,ic,FALSE);
4345 pic16_aopOp (result,ic,TRUE);
4347 /* special cases first */
4349 if (AOP_TYPE(left) == AOP_CRY &&
4350 AOP_TYPE(right)== AOP_CRY) {
4351 genDivbits(left,right,result);
4355 /* if both are of size == 1 */
4356 if (AOP_SIZE(left) == 1 &&
4357 AOP_SIZE(right) == 1 ) {
4358 genDivOneByte(left,right,result);
4362 /* should have been converted to function call */
4365 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4366 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4367 pic16_freeAsmop(result,NULL,ic,TRUE);
4370 /*-----------------------------------------------------------------*/
4371 /* genModbits :- modulus of bits */
4372 /*-----------------------------------------------------------------*/
4373 static void genModbits (operand *left,
4380 /* the result must be bit */
4381 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4382 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4386 pic16_emitcode("div","ab");
4387 pic16_emitcode("mov","a,b");
4388 pic16_emitcode("rrc","a");
4389 pic16_aopPut(AOP(result),"c",0);
4392 /*-----------------------------------------------------------------*/
4393 /* genModOneByte : 8 bit modulus */
4394 /*-----------------------------------------------------------------*/
4395 static void genModOneByte (operand *left,
4399 sym_link *opetype = operandType(result);
4403 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4404 /* signed or unsigned */
4405 if (SPEC_USIGN(opetype)) {
4406 /* unsigned is easy */
4407 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4408 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4410 pic16_emitcode("div","ab");
4411 pic16_aopPut(AOP(result),"b",0);
4415 /* signed is a little bit more difficult */
4417 /* save the signs of the operands */
4418 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4421 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4422 pic16_emitcode("push","acc"); /* save it on the stack */
4424 /* now sign adjust for both left & right */
4425 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4428 lbl = newiTempLabel(NULL);
4429 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4430 pic16_emitcode("cpl","a");
4431 pic16_emitcode("inc","a");
4432 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4433 pic16_emitcode("mov","b,a");
4435 /* sign adjust left side */
4436 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4439 lbl = newiTempLabel(NULL);
4440 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4441 pic16_emitcode("cpl","a");
4442 pic16_emitcode("inc","a");
4443 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4445 /* now the multiplication */
4446 pic16_emitcode("div","ab");
4447 /* we are interested in the lower order
4449 lbl = newiTempLabel(NULL);
4450 pic16_emitcode("pop","acc");
4451 /* if there was an over flow we don't
4452 adjust the sign of the result */
4453 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4454 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4456 pic16_emitcode("clr","a");
4457 pic16_emitcode("subb","a,b");
4458 pic16_emitcode("mov","b,a");
4459 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4461 /* now we are done */
4462 pic16_aopPut(AOP(result),"b",0);
4466 /*-----------------------------------------------------------------*/
4467 /* genMod - generates code for division */
4468 /*-----------------------------------------------------------------*/
4469 static void genMod (iCode *ic)
4471 operand *left = IC_LEFT(ic);
4472 operand *right = IC_RIGHT(ic);
4473 operand *result= IC_RESULT(ic);
4475 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4476 /* assign the amsops */
4477 pic16_aopOp (left,ic,FALSE);
4478 pic16_aopOp (right,ic,FALSE);
4479 pic16_aopOp (result,ic,TRUE);
4481 /* special cases first */
4483 if (AOP_TYPE(left) == AOP_CRY &&
4484 AOP_TYPE(right)== AOP_CRY) {
4485 genModbits(left,right,result);
4489 /* if both are of size == 1 */
4490 if (AOP_SIZE(left) == 1 &&
4491 AOP_SIZE(right) == 1 ) {
4492 genModOneByte(left,right,result);
4496 /* should have been converted to function call */
4500 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4501 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4502 pic16_freeAsmop(result,NULL,ic,TRUE);
4505 /*-----------------------------------------------------------------*/
4506 /* genIfxJump :- will create a jump depending on the ifx */
4507 /*-----------------------------------------------------------------*/
4509 note: May need to add parameter to indicate when a variable is in bit space.
4511 static void genIfxJump (iCode *ic, char *jval)
4514 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4515 /* if true label then we jump if condition
4517 if ( IC_TRUE(ic) ) {
4519 if(strcmp(jval,"a") == 0)
4521 else if (strcmp(jval,"c") == 0)
4524 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4525 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4528 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4529 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4533 /* false label is present */
4534 if(strcmp(jval,"a") == 0)
4536 else if (strcmp(jval,"c") == 0)
4539 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4540 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4543 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4544 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4549 /* mark the icode as generated */
4556 /*-----------------------------------------------------------------*/
4558 /*-----------------------------------------------------------------*/
4559 static void genSkip(iCode *ifx,int status_bit)
4561 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4565 if ( IC_TRUE(ifx) ) {
4566 switch(status_bit) {
4581 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4582 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4586 switch(status_bit) {
4600 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4601 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4608 /*-----------------------------------------------------------------*/
4610 /*-----------------------------------------------------------------*/
4611 static void genSkipc(resolvedIfx *rifx)
4613 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4623 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4624 rifx->generated = 1;
4627 /*-----------------------------------------------------------------*/
4629 /*-----------------------------------------------------------------*/
4630 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4632 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4637 if( (rifx->condition ^ invert_condition) & 1)
4642 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4643 rifx->generated = 1;
4647 /*-----------------------------------------------------------------*/
4649 /*-----------------------------------------------------------------*/
4650 static void genSkipz(iCode *ifx, int condition)
4661 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4663 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4666 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4668 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4673 /*-----------------------------------------------------------------*/
4675 /*-----------------------------------------------------------------*/
4676 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4682 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4684 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4687 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4688 rifx->generated = 1;
4692 /*-----------------------------------------------------------------*/
4693 /* genChkZeroes :- greater or less than comparison */
4694 /* For each byte in a literal that is zero, inclusive or the */
4695 /* the corresponding byte in the operand with W */
4696 /* returns true if any of the bytes are zero */
4697 /*-----------------------------------------------------------------*/
4698 static int genChkZeroes(operand *op, int lit, int size)
4705 i = (lit >> (size*8)) & 0xff;
4709 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4711 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4720 /*-----------------------------------------------------------------*/
4721 /* genCmp :- greater or less than comparison */
4722 /*-----------------------------------------------------------------*/
4723 static void genCmp (operand *left,operand *right,
4724 operand *result, iCode *ifx, int sign)
4726 int size; //, offset = 0 ;
4727 unsigned long lit = 0L,i = 0;
4728 resolvedIfx rFalseIfx;
4729 // resolvedIfx rTrueIfx;
4731 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4734 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4735 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4739 resolveIfx(&rFalseIfx,ifx);
4740 truelbl = newiTempLabel(NULL);
4741 size = max(AOP_SIZE(left),AOP_SIZE(right));
4743 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4747 /* if literal is on the right then swap with left */
4748 if ((AOP_TYPE(right) == AOP_LIT)) {
4749 operand *tmp = right ;
4750 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4751 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4754 lit = (lit - 1) & mask;
4757 rFalseIfx.condition ^= 1;
4760 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4761 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4765 //if(IC_TRUE(ifx) == NULL)
4766 /* if left & right are bit variables */
4767 if (AOP_TYPE(left) == AOP_CRY &&
4768 AOP_TYPE(right) == AOP_CRY ) {
4769 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4770 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4772 /* subtract right from left if at the
4773 end the carry flag is set then we know that
4774 left is greater than right */
4776 symbol *lbl = newiTempLabel(NULL);
4779 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4780 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4784 if(AOP_TYPE(right) == AOP_LIT) {
4786 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4788 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4795 genSkipCond(&rFalseIfx,left,size-1,7);
4797 /* no need to compare to 0...*/
4798 /* NOTE: this is a de-generate compare that most certainly
4799 * creates some dead code. */
4800 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4802 if(ifx) ifx->generated = 1;
4809 //i = (lit >> (size*8)) & 0xff;
4810 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4812 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4814 i = ((0-lit) & 0xff);
4817 /* lit is 0x7f, all signed chars are less than
4818 * this except for 0x7f itself */
4819 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4820 genSkipz2(&rFalseIfx,0);
4822 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4823 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4824 genSkipc(&rFalseIfx);
4829 genSkipz2(&rFalseIfx,1);
4831 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4832 genSkipc(&rFalseIfx);
4836 if(ifx) ifx->generated = 1;
4840 /* chars are out of the way. now do ints and longs */
4843 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4850 genSkipCond(&rFalseIfx,left,size,7);
4851 if(ifx) ifx->generated = 1;
4856 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4858 //rFalseIfx.condition ^= 1;
4859 //genSkipCond(&rFalseIfx,left,size,7);
4860 //rFalseIfx.condition ^= 1;
4862 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4863 if(rFalseIfx.condition)
4864 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4866 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4868 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4869 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4870 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4873 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4875 if(rFalseIfx.condition) {
4877 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4883 genSkipc(&rFalseIfx);
4884 pic16_emitpLabel(truelbl->key);
4885 if(ifx) ifx->generated = 1;
4892 if( (lit & 0xff) == 0) {
4893 /* lower byte is zero */
4894 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4895 i = ((lit >> 8) & 0xff) ^0x80;
4896 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4897 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4898 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4899 genSkipc(&rFalseIfx);
4902 if(ifx) ifx->generated = 1;
4907 /* Special cases for signed longs */
4908 if( (lit & 0xffffff) == 0) {
4909 /* lower byte is zero */
4910 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4911 i = ((lit >> 8*3) & 0xff) ^0x80;
4912 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4913 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4914 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4915 genSkipc(&rFalseIfx);
4918 if(ifx) ifx->generated = 1;
4926 if(lit & (0x80 << (size*8))) {
4927 /* lit is negative */
4928 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4930 //genSkipCond(&rFalseIfx,left,size,7);
4932 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4934 if(rFalseIfx.condition)
4935 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4937 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4941 /* lit is positive */
4942 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4943 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4944 if(rFalseIfx.condition)
4945 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4947 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4952 This works, but is only good for ints.
4953 It also requires a "known zero" register.
4954 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4955 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4956 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
4957 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4958 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4959 genSkipc(&rFalseIfx);
4961 pic16_emitpLabel(truelbl->key);
4962 if(ifx) ifx->generated = 1;
4966 /* There are no more special cases, so perform a general compare */
4968 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4969 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4973 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4975 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4977 //rFalseIfx.condition ^= 1;
4978 genSkipc(&rFalseIfx);
4980 pic16_emitpLabel(truelbl->key);
4982 if(ifx) ifx->generated = 1;
4989 /* sign is out of the way. So now do an unsigned compare */
4990 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4993 /* General case - compare to an unsigned literal on the right.*/
4995 i = (lit >> (size*8)) & 0xff;
4996 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4997 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4999 i = (lit >> (size*8)) & 0xff;
5002 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5004 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5006 /* this byte of the lit is zero,
5007 *if it's not the last then OR in the variable */
5009 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5014 pic16_emitpLabel(lbl->key);
5015 // pic16_emitpLabel(truelbl->key);
5016 //if(emitFinalCheck)
5017 genSkipc(&rFalseIfx);
5019 pic16_emitpLabel(truelbl->key);
5021 if(ifx) ifx->generated = 1;
5028 if(AOP_TYPE(left) == AOP_LIT) {
5029 //symbol *lbl = newiTempLabel(NULL);
5031 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5034 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5037 if((lit == 0) && (sign == 0)){
5040 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5042 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5044 genSkipz2(&rFalseIfx,0);
5045 if(ifx) ifx->generated = 1;
5052 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5053 /* degenerate compare can never be true */
5054 if(rFalseIfx.condition == 0)
5055 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5057 if(ifx) ifx->generated = 1;
5062 /* signed comparisons to a literal byte */
5064 int lp1 = (lit+1) & 0xff;
5066 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5069 rFalseIfx.condition ^= 1;
5070 genSkipCond(&rFalseIfx,right,0,7);
5073 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5074 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5075 genSkipz2(&rFalseIfx,1);
5078 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5079 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5080 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5081 rFalseIfx.condition ^= 1;
5082 genSkipc(&rFalseIfx);
5086 /* unsigned comparisons to a literal byte */
5088 switch(lit & 0xff ) {
5090 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5091 genSkipz2(&rFalseIfx,0);
5094 rFalseIfx.condition ^= 1;
5095 genSkipCond(&rFalseIfx,right,0,7);
5099 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5100 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5101 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5102 rFalseIfx.condition ^= 1;
5103 if (AOP_TYPE(result) == AOP_CRY)
5104 genSkipc(&rFalseIfx);
5106 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5107 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5113 if(ifx) ifx->generated = 1;
5114 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5120 /* Size is greater than 1 */
5128 /* this means lit = 0xffffffff, or -1 */
5131 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5132 rFalseIfx.condition ^= 1;
5133 genSkipCond(&rFalseIfx,right,size,7);
5134 if(ifx) ifx->generated = 1;
5141 if(rFalseIfx.condition) {
5142 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5143 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5146 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5148 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5152 if(rFalseIfx.condition) {
5153 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5154 pic16_emitpLabel(truelbl->key);
5156 rFalseIfx.condition ^= 1;
5157 genSkipCond(&rFalseIfx,right,s,7);
5160 if(ifx) ifx->generated = 1;
5164 if((size == 1) && (0 == (lp1&0xff))) {
5165 /* lower byte of signed word is zero */
5166 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5167 i = ((lp1 >> 8) & 0xff) ^0x80;
5168 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5169 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5170 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5171 rFalseIfx.condition ^= 1;
5172 genSkipc(&rFalseIfx);
5175 if(ifx) ifx->generated = 1;
5179 if(lit & (0x80 << (size*8))) {
5180 /* Lit is less than zero */
5181 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5182 //rFalseIfx.condition ^= 1;
5183 //genSkipCond(&rFalseIfx,left,size,7);
5184 //rFalseIfx.condition ^= 1;
5185 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5186 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5188 if(rFalseIfx.condition)
5189 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5191 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5195 /* Lit is greater than or equal to zero */
5196 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5197 //rFalseIfx.condition ^= 1;
5198 //genSkipCond(&rFalseIfx,right,size,7);
5199 //rFalseIfx.condition ^= 1;
5201 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5202 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5204 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5205 if(rFalseIfx.condition)
5206 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5208 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5213 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5214 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5218 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5220 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5222 rFalseIfx.condition ^= 1;
5223 //rFalseIfx.condition = 1;
5224 genSkipc(&rFalseIfx);
5226 pic16_emitpLabel(truelbl->key);
5228 if(ifx) ifx->generated = 1;
5233 /* compare word or long to an unsigned literal on the right.*/
5238 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5241 break; /* handled above */
5244 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5246 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5247 genSkipz2(&rFalseIfx,0);
5251 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5253 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5256 if(rFalseIfx.condition)
5257 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5259 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5262 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5263 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5265 rFalseIfx.condition ^= 1;
5266 genSkipc(&rFalseIfx);
5269 pic16_emitpLabel(truelbl->key);
5271 if(ifx) ifx->generated = 1;
5277 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5278 i = (lit >> (size*8)) & 0xff;
5280 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5281 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5284 i = (lit >> (size*8)) & 0xff;
5287 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5289 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5291 /* this byte of the lit is zero,
5292 * if it's not the last then OR in the variable */
5294 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5299 pic16_emitpLabel(lbl->key);
5301 rFalseIfx.condition ^= 1;
5303 genSkipc(&rFalseIfx);
5307 pic16_emitpLabel(truelbl->key);
5308 if(ifx) ifx->generated = 1;
5312 /* Compare two variables */
5314 DEBUGpic16_emitcode(";sign","%d",sign);
5318 /* Sigh. thus sucks... */
5322 pctemp = pic16_popGetTempReg();
5323 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5324 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5325 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5326 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5327 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5328 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5329 pic16_popReleaseTempReg(pctemp);
5331 /* Signed char comparison */
5332 /* Special thanks to Nikolai Golovchenko for this snippet */
5333 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5334 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5335 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5336 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5337 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5338 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5340 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5341 genSkipc(&rFalseIfx);
5343 if(ifx) ifx->generated = 1;
5349 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5350 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5354 /* The rest of the bytes of a multi-byte compare */
5358 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5361 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5362 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5367 pic16_emitpLabel(lbl->key);
5369 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5370 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5371 (AOP_TYPE(result) == AOP_REG)) {
5372 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5373 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5375 genSkipc(&rFalseIfx);
5377 //genSkipc(&rFalseIfx);
5378 if(ifx) ifx->generated = 1;
5385 if ((AOP_TYPE(result) != AOP_CRY)
5386 && AOP_SIZE(result)) {
5387 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5389 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5391 pic16_outBitC(result);
5393 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5394 /* if the result is used in the next
5395 ifx conditional branch then generate
5396 code a little differently */
5398 genIfxJump (ifx,"c");
5400 pic16_outBitC(result);
5401 /* leave the result in acc */
5406 /*-----------------------------------------------------------------*/
5407 /* genCmpGt :- greater than comparison */
5408 /*-----------------------------------------------------------------*/
5409 static void genCmpGt (iCode *ic, iCode *ifx)
5411 operand *left, *right, *result;
5412 sym_link *letype , *retype;
5415 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5417 right= IC_RIGHT(ic);
5418 result = IC_RESULT(ic);
5420 letype = getSpec(operandType(left));
5421 retype =getSpec(operandType(right));
5422 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5423 /* assign the amsops */
5424 pic16_aopOp (left,ic,FALSE);
5425 pic16_aopOp (right,ic,FALSE);
5426 pic16_aopOp (result,ic,TRUE);
5428 genCmp(right, left, result, ifx, sign);
5430 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5431 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5432 pic16_freeAsmop(result,NULL,ic,TRUE);
5435 /*-----------------------------------------------------------------*/
5436 /* genCmpLt - less than comparisons */
5437 /*-----------------------------------------------------------------*/
5438 static void genCmpLt (iCode *ic, iCode *ifx)
5440 operand *left, *right, *result;
5441 sym_link *letype , *retype;
5444 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5446 right= IC_RIGHT(ic);
5447 result = IC_RESULT(ic);
5449 letype = getSpec(operandType(left));
5450 retype =getSpec(operandType(right));
5451 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5453 /* assign the amsops */
5454 pic16_aopOp (left,ic,FALSE);
5455 pic16_aopOp (right,ic,FALSE);
5456 pic16_aopOp (result,ic,TRUE);
5458 genCmp(left, right, result, ifx, sign);
5460 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5461 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5462 pic16_freeAsmop(result,NULL,ic,TRUE);
5467 // FIXME reenable literal optimisation when the pic16 port is stable
5469 /*-----------------------------------------------------------------*/
5470 /* genc16bit2lit - compare a 16 bit value to a literal */
5471 /*-----------------------------------------------------------------*/
5472 static void genc16bit2lit(operand *op, int lit, int offset)
5476 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
5477 if( (lit&0xff) == 0)
5482 switch( BYTEofLONG(lit,i)) {
5484 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5487 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5490 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5493 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5494 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5499 switch( BYTEofLONG(lit,i)) {
5501 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5505 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5509 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5512 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5514 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5523 /*-----------------------------------------------------------------*/
5524 /* gencjneshort - compare and jump if not equal */
5525 /*-----------------------------------------------------------------*/
5526 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5528 int size = max(AOP_SIZE(left),AOP_SIZE(right));
5530 int res_offset = 0; /* the result may be a different size then left or right */
5531 int res_size = AOP_SIZE(result);
5533 symbol *lbl, *lbl_done;
5535 unsigned long lit = 0L;
5536 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5538 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5539 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5541 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
5542 resolveIfx(&rIfx,ifx);
5543 lbl = newiTempLabel(NULL);
5544 lbl_done = newiTempLabel(NULL);
5547 /* if the left side is a literal or
5548 if the right is in a pointer register and left
5550 if ((AOP_TYPE(left) == AOP_LIT) ||
5551 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5556 if(AOP_TYPE(right) == AOP_LIT)
5557 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5559 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5560 preserve_result = 1;
5562 if(result && !preserve_result)
5565 for(i = 0; i < AOP_SIZE(result); i++)
5566 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5570 /* if the right side is a literal then anything goes */
5571 if (AOP_TYPE(right) == AOP_LIT &&
5572 AOP_TYPE(left) != AOP_DIR ) {
5575 genc16bit2lit(left, lit, 0);
5577 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5580 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5583 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5584 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5586 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5590 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5592 if(res_offset < res_size-1)
5600 /* if the right side is in a register or in direct space or
5601 if the left is a pointer register & right is not */
5602 else if (AOP_TYPE(right) == AOP_REG ||
5603 AOP_TYPE(right) == AOP_DIR ||
5604 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5605 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5606 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5607 int lbl_key = lbl->key;
5610 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5611 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5613 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5614 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5615 __FUNCTION__,__LINE__);
5619 /* switch(size) { */
5621 /* genc16bit2lit(left, lit, 0); */
5623 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5628 if((AOP_TYPE(left) == AOP_DIR) &&
5629 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5631 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5632 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5634 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5636 switch (lit & 0xff) {
5638 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5641 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5642 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5643 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5647 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5648 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5649 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5650 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5654 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5655 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5660 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5663 if(AOP_TYPE(result) == AOP_CRY) {
5664 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5669 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5671 /* fix me. probably need to check result size too */
5672 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5677 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5678 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5685 if(res_offset < res_size-1)
5690 } else if(AOP_TYPE(right) == AOP_REG &&
5691 AOP_TYPE(left) != AOP_DIR){
5694 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5695 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5696 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5701 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5703 if(res_offset < res_size-1)
5708 /* right is a pointer reg need both a & b */
5710 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5712 pic16_emitcode("mov","b,%s",l);
5713 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5714 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5719 if(result && preserve_result)
5722 for(i = 0; i < AOP_SIZE(result); i++)
5723 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5726 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5728 if(result && preserve_result)
5729 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5732 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5734 pic16_emitpLabel(lbl->key);
5736 if(result && preserve_result)
5739 for(i = 0; i < AOP_SIZE(result); i++)
5740 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5742 pic16_emitpLabel(lbl_done->key);
5745 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5753 /*-----------------------------------------------------------------*/
5754 /* gencjne - compare and jump if not equal */
5755 /*-----------------------------------------------------------------*/
5756 static void gencjne(operand *left, operand *right, iCode *ifx)
5758 symbol *tlbl = newiTempLabel(NULL);
5760 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5761 gencjneshort(left, right, lbl);
5763 pic16_emitcode("mov","a,%s",one);
5764 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5765 pic16_emitcode("","%05d_DS_:",lbl->key+100);
5766 pic16_emitcode("clr","a");
5767 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5769 pic16_emitpLabel(lbl->key);
5770 pic16_emitpLabel(tlbl->key);
5776 /*-----------------------------------------------------------------*/
5777 /* is_LitOp - check if operand has to be treated as literal */
5778 /*-----------------------------------------------------------------*/
5779 static bool is_LitOp(operand *op)
5781 return (AOP_TYPE(op) == AOP_LIT)
5782 || ( (AOP_TYPE(op) == AOP_PCODE)
5783 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5784 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));
5787 /*-----------------------------------------------------------------*/
5788 /* is_LitAOp - check if operand has to be treated as literal */
5789 /*-----------------------------------------------------------------*/
5790 static bool is_LitAOp(asmop *aop)
5792 return (aop->type == AOP_LIT)
5793 || ( (aop->type == AOP_PCODE)
5794 && ( (aop->aopu.pcop->type == PO_LITERAL)
5795 || (aop->aopu.pcop->type == PO_IMMEDIATE) ));
5800 /*-----------------------------------------------------------------*/
5801 /* genCmpEq - generates code for equal to */
5802 /*-----------------------------------------------------------------*/
5803 static void genCmpEq (iCode *ic, iCode *ifx)
5805 operand *left, *right, *result;
5806 symbol *falselbl = newiTempLabel(NULL);
5807 symbol *donelbl = newiTempLabel(NULL);
5809 int preserve_result = 0;
5810 int generate_result = 0;
5813 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5814 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5815 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5817 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5818 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5820 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5822 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5823 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5827 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5829 operand *tmp = right ;
5834 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5835 preserve_result = 1;
5837 if(result && AOP_SIZE(result))
5838 generate_result = 1;
5840 if(generate_result && !preserve_result)
5842 for(i = 0; i < AOP_SIZE(result); i++)
5843 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5846 for(i=0; i < AOP_SIZE(left); i++)
5848 if(AOP_TYPE(left) != AOP_ACC)
5851 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5853 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5856 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
5858 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
5860 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5865 if(generate_result && preserve_result)
5867 for(i = 0; i < AOP_SIZE(result); i++)
5868 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5872 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5874 if(generate_result && preserve_result)
5875 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5877 if(ifx && IC_TRUE(ifx))
5878 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5880 if(ifx && IC_FALSE(ifx))
5881 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5883 pic16_emitpLabel(falselbl->key);
5887 if(ifx && IC_FALSE(ifx))
5888 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5890 if(generate_result && preserve_result)
5892 for(i = 0; i < AOP_SIZE(result); i++)
5893 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5896 pic16_emitpLabel(donelbl->key);
5902 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5903 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5904 pic16_freeAsmop(result,NULL,ic,TRUE);
5910 // old version kept for reference
5912 /*-----------------------------------------------------------------*/
5913 /* genCmpEq - generates code for equal to */
5914 /*-----------------------------------------------------------------*/
5915 static void genCmpEq (iCode *ic, iCode *ifx)
5917 operand *left, *right, *result;
5918 unsigned long lit = 0L;
5920 symbol *falselbl = newiTempLabel(NULL);
5923 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5926 DEBUGpic16_emitcode ("; ifx is non-null","");
5928 DEBUGpic16_emitcode ("; ifx is null","");
5930 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5931 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5932 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5934 size = max(AOP_SIZE(left),AOP_SIZE(right));
5936 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5938 /* if literal, literal on the right or
5939 if the right is in a pointer register and left
5941 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
5942 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5943 operand *tmp = right ;
5949 if(ifx && !AOP_SIZE(result)){
5951 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
5952 /* if they are both bit variables */
5953 if (AOP_TYPE(left) == AOP_CRY &&
5954 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5955 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
5956 if(AOP_TYPE(right) == AOP_LIT){
5957 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5959 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5960 pic16_emitcode("cpl","c");
5961 } else if(lit == 1L) {
5962 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5964 pic16_emitcode("clr","c");
5966 /* AOP_TYPE(right) == AOP_CRY */
5968 symbol *lbl = newiTempLabel(NULL);
5969 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5970 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5971 pic16_emitcode("cpl","c");
5972 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5974 /* if true label then we jump if condition
5976 tlbl = newiTempLabel(NULL);
5977 if ( IC_TRUE(ifx) ) {
5978 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5979 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5981 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5982 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5984 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5987 /* left and right are both bit variables, result is carry */
5990 resolveIfx(&rIfx,ifx);
5992 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5993 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5994 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5995 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6000 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6002 /* They're not both bit variables. Is the right a literal? */
6003 if(AOP_TYPE(right) == AOP_LIT) {
6004 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6009 switch(lit & 0xff) {
6011 if ( IC_TRUE(ifx) ) {
6012 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6014 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6016 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6017 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6021 if ( IC_TRUE(ifx) ) {
6022 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6024 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6026 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6027 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6031 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6033 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6038 /* end of size == 1 */
6042 genc16bit2lit(left,lit,offset);
6045 /* end of size == 2 */
6050 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6051 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6052 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6053 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6056 /* search for patterns that can be optimized */
6058 genc16bit2lit(left,lit,0);
6062 emitSKPZ; // if hi word unequal
6064 emitSKPNZ; // if hi word equal
6066 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6067 genc16bit2lit(left,lit,2);
6070 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6071 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6075 pic16_emitpLabel(falselbl->key);
6084 } else if(AOP_TYPE(right) == AOP_CRY ) {
6085 /* we know the left is not a bit, but that the right is */
6086 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6087 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6088 pic16_popGet(AOP(right),offset));
6089 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6091 /* if the two are equal, then W will be 0 and the Z bit is set
6092 * we could test Z now, or go ahead and check the high order bytes if
6093 * the variable we're comparing is larger than a byte. */
6096 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6098 if ( IC_TRUE(ifx) ) {
6100 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6101 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6104 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6105 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6109 /* They're both variables that are larger than bits */
6112 tlbl = newiTempLabel(NULL);
6115 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6116 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6118 if ( IC_TRUE(ifx) ) {
6122 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6124 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6125 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6129 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6132 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6133 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6138 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6140 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6141 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6145 if(s>1 && IC_TRUE(ifx)) {
6146 pic16_emitpLabel(tlbl->key);
6147 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6151 /* mark the icode as generated */
6156 /* if they are both bit variables */
6157 if (AOP_TYPE(left) == AOP_CRY &&
6158 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6159 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
6160 if(AOP_TYPE(right) == AOP_LIT){
6161 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6163 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6164 pic16_emitcode("cpl","c");
6165 } else if(lit == 1L) {
6166 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6168 pic16_emitcode("clr","c");
6170 /* AOP_TYPE(right) == AOP_CRY */
6172 symbol *lbl = newiTempLabel(NULL);
6173 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6174 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6175 pic16_emitcode("cpl","c");
6176 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6179 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6180 pic16_outBitC(result);
6184 genIfxJump (ifx,"c");
6187 /* if the result is used in an arithmetic operation
6188 then put the result in place */
6189 pic16_outBitC(result);
6192 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
6193 gencjne(left,right,result,ifx);
6196 gencjne(left,right,newiTempLabel(NULL));
6198 if(IC_TRUE(ifx)->key)
6199 gencjne(left,right,IC_TRUE(ifx)->key);
6201 gencjne(left,right,IC_FALSE(ifx)->key);
6205 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6206 pic16_aopPut(AOP(result),"a",0);
6211 genIfxJump (ifx,"a");
6215 /* if the result is used in an arithmetic operation
6216 then put the result in place */
6218 if (AOP_TYPE(result) != AOP_CRY)
6219 pic16_outAcc(result);
6221 /* leave the result in acc */
6225 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6226 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6227 pic16_freeAsmop(result,NULL,ic,TRUE);
6231 /*-----------------------------------------------------------------*/
6232 /* ifxForOp - returns the icode containing the ifx for operand */
6233 /*-----------------------------------------------------------------*/
6234 static iCode *ifxForOp ( operand *op, iCode *ic )
6236 /* if true symbol then needs to be assigned */
6237 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6238 if (IS_TRUE_SYMOP(op))
6241 /* if this has register type condition and
6242 the next instruction is ifx with the same operand
6243 and live to of the operand is upto the ifx only then */
6245 && ic->next->op == IFX
6246 && IC_COND(ic->next)->key == op->key
6247 && OP_SYMBOL(op)->liveTo <= ic->next->seq
6249 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6254 ic->next->op == IFX &&
6255 IC_COND(ic->next)->key == op->key) {
6256 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6260 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6262 ic->next->op == IFX)
6263 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6266 ic->next->op == IFX &&
6267 IC_COND(ic->next)->key == op->key) {
6268 DEBUGpic16_emitcode ("; "," key is okay");
6269 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6270 OP_SYMBOL(op)->liveTo,
6275 /* the code below is completely untested
6276 * it just allows ulong2fs.c compile -- VR */
6279 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6280 __FILE__, __FUNCTION__, __LINE__);
6282 /* if this has register type condition and
6283 the next instruction is ifx with the same operand
6284 and live to of the operand is upto the ifx only then */
6286 ic->next->op == IFX &&
6287 IC_COND(ic->next)->key == op->key &&
6288 OP_SYMBOL(op)->liveTo <= ic->next->seq )
6292 ic->next->op == IFX &&
6293 IC_COND(ic->next)->key == op->key) {
6294 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6298 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6299 __FILE__, __FUNCTION__, __LINE__);
6301 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
6306 /*-----------------------------------------------------------------*/
6307 /* genAndOp - for && operation */
6308 /*-----------------------------------------------------------------*/
6309 static void genAndOp (iCode *ic)
6311 operand *left,*right, *result;
6314 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6315 /* note here that && operations that are in an
6316 if statement are taken away by backPatchLabels
6317 only those used in arthmetic operations remain */
6318 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6319 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6320 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6322 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6324 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6325 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6326 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6328 /* if both are bit variables */
6329 /* if (AOP_TYPE(left) == AOP_CRY && */
6330 /* AOP_TYPE(right) == AOP_CRY ) { */
6331 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6332 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6333 /* pic16_outBitC(result); */
6335 /* tlbl = newiTempLabel(NULL); */
6336 /* pic16_toBoolean(left); */
6337 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6338 /* pic16_toBoolean(right); */
6339 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6340 /* pic16_outBitAcc(result); */
6343 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6344 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6345 pic16_freeAsmop(result,NULL,ic,TRUE);
6349 /*-----------------------------------------------------------------*/
6350 /* genOrOp - for || operation */
6351 /*-----------------------------------------------------------------*/
6354 modified this code, but it doesn't appear to ever get called
6357 static void genOrOp (iCode *ic)
6359 operand *left,*right, *result;
6362 /* note here that || operations that are in an
6363 if statement are taken away by backPatchLabels
6364 only those used in arthmetic operations remain */
6365 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6366 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6367 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6368 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6370 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6372 /* if both are bit variables */
6373 if (AOP_TYPE(left) == AOP_CRY &&
6374 AOP_TYPE(right) == AOP_CRY ) {
6375 pic16_emitcode("clrc","");
6376 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6377 AOP(left)->aopu.aop_dir,
6378 AOP(left)->aopu.aop_dir);
6379 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6380 AOP(right)->aopu.aop_dir,
6381 AOP(right)->aopu.aop_dir);
6382 pic16_emitcode("setc","");
6385 tlbl = newiTempLabel(NULL);
6386 pic16_toBoolean(left);
6388 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6389 pic16_toBoolean(right);
6390 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6392 pic16_outBitAcc(result);
6395 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6396 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6397 pic16_freeAsmop(result,NULL,ic,TRUE);
6400 /*-----------------------------------------------------------------*/
6401 /* isLiteralBit - test if lit == 2^n */
6402 /*-----------------------------------------------------------------*/
6403 static int isLiteralBit(unsigned long lit)
6405 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6406 0x100L,0x200L,0x400L,0x800L,
6407 0x1000L,0x2000L,0x4000L,0x8000L,
6408 0x10000L,0x20000L,0x40000L,0x80000L,
6409 0x100000L,0x200000L,0x400000L,0x800000L,
6410 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6411 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6414 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6415 for(idx = 0; idx < 32; idx++)
6421 /*-----------------------------------------------------------------*/
6422 /* continueIfTrue - */
6423 /*-----------------------------------------------------------------*/
6424 static void continueIfTrue (iCode *ic)
6426 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6428 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6432 /*-----------------------------------------------------------------*/
6434 /*-----------------------------------------------------------------*/
6435 static void jumpIfTrue (iCode *ic)
6437 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6439 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6443 /*-----------------------------------------------------------------*/
6444 /* jmpTrueOrFalse - */
6445 /*-----------------------------------------------------------------*/
6446 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6448 // ugly but optimized by peephole
6449 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6451 symbol *nlbl = newiTempLabel(NULL);
6452 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
6453 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6454 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6455 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6458 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6459 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6464 /*-----------------------------------------------------------------*/
6465 /* genAnd - code for and */
6466 /*-----------------------------------------------------------------*/
6467 static void genAnd (iCode *ic, iCode *ifx)
6469 operand *left, *right, *result;
6471 unsigned long lit = 0L;
6476 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6477 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6478 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6479 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6481 resolveIfx(&rIfx,ifx);
6483 /* if left is a literal & right is not then exchange them */
6484 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6485 AOP_NEEDSACC(left)) {
6486 operand *tmp = right ;
6491 /* if result = right then exchange them */
6492 if(pic16_sameRegs(AOP(result),AOP(right))){
6493 operand *tmp = right ;
6498 /* if right is bit then exchange them */
6499 if (AOP_TYPE(right) == AOP_CRY &&
6500 AOP_TYPE(left) != AOP_CRY){
6501 operand *tmp = right ;
6505 if(AOP_TYPE(right) == AOP_LIT)
6506 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6508 size = AOP_SIZE(result);
6510 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6513 // result = bit & yy;
6514 if (AOP_TYPE(left) == AOP_CRY){
6515 // c = bit & literal;
6516 if(AOP_TYPE(right) == AOP_LIT){
6518 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6521 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6524 if(size && (AOP_TYPE(result) == AOP_CRY)){
6525 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6528 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6532 pic16_emitcode("clr","c");
6535 if (AOP_TYPE(right) == AOP_CRY){
6537 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6538 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6541 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6543 pic16_emitcode("rrc","a");
6544 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6550 pic16_outBitC(result);
6552 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6553 genIfxJump(ifx, "c");
6557 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6558 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6559 if((AOP_TYPE(right) == AOP_LIT) &&
6560 (AOP_TYPE(result) == AOP_CRY) &&
6561 (AOP_TYPE(left) != AOP_CRY)){
6562 int posbit = isLiteralBit(lit);
6566 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6569 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6575 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6576 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6578 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6579 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6582 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6583 size = AOP_SIZE(left);
6586 int bp = posbit, ofs=0;
6593 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6594 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
6598 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6599 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6601 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6608 symbol *tlbl = newiTempLabel(NULL);
6609 int sizel = AOP_SIZE(left);
6615 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
6617 /* patch provided by Aaron Colwell */
6618 if((posbit = isLiteralBit(bytelit)) != 0) {
6619 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
6620 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
6621 (posbit-1),0, PO_GPR_REGISTER));
6623 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
6624 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
6626 if (bytelit == 0xff) {
6627 /* Aaron had a MOVF instruction here, changed to MOVFW cause
6628 * a peephole could optimize it out -- VR */
6629 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6631 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6632 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
6635 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
6636 pic16_popGetLabel(tlbl->key));
6640 /* old code, left here for reference -- VR 09/2004 */
6641 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6643 if((posbit = isLiteralBit(bytelit)) != 0)
6644 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6646 if(bytelit != 0x0FFL)
6647 pic16_emitcode("anl","a,%s",
6648 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6649 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6655 // bit = left & literal
6658 pic16_emitpLabel(tlbl->key);
6660 // if(left & literal)
6663 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
6664 pic16_emitpLabel(tlbl->key);
6671 pic16_outBitC(result);
6675 /* if left is same as result */
6676 if(pic16_sameRegs(AOP(result),AOP(left))){
6678 for(;size--; offset++,lit>>=8) {
6679 if(AOP_TYPE(right) == AOP_LIT){
6680 switch(lit & 0xff) {
6682 /* and'ing with 0 has clears the result */
6683 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6684 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6687 /* and'ing with 0xff is a nop when the result and left are the same */
6692 int p = my_powof2( (~lit) & 0xff );
6694 /* only one bit is set in the literal, so use a bcf instruction */
6695 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6696 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6699 pic16_emitcode("movlw","0x%x", (lit & 0xff));
6700 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6701 if(know_W != (lit&0xff))
6702 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6704 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6709 if (AOP_TYPE(left) == AOP_ACC) {
6710 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6712 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6713 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6720 // left & result in different registers
6721 if(AOP_TYPE(result) == AOP_CRY){
6723 // if(size), result in bit
6724 // if(!size && ifx), conditional oper: if(left & right)
6725 symbol *tlbl = newiTempLabel(NULL);
6726 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6728 pic16_emitcode("setb","c");
6730 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6731 pic16_emitcode("anl","a,%s",
6732 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6733 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6738 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6739 pic16_outBitC(result);
6741 jmpTrueOrFalse(ifx, tlbl);
6743 for(;(size--);offset++) {
6745 // result = left & right
6746 if(AOP_TYPE(right) == AOP_LIT){
6747 int t = (lit >> (offset*8)) & 0x0FFL;
6750 pic16_emitcode("clrf","%s",
6751 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6752 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6755 pic16_emitcode("movf","%s,w",
6756 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6757 pic16_emitcode("movwf","%s",
6758 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6759 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6760 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6763 pic16_emitcode("movlw","0x%x",t);
6764 pic16_emitcode("andwf","%s,w",
6765 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6766 pic16_emitcode("movwf","%s",
6767 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6769 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6770 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6771 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6776 if (AOP_TYPE(left) == AOP_ACC) {
6777 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6778 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6780 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6781 pic16_emitcode("andwf","%s,w",
6782 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6783 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6784 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6786 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6787 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6793 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6794 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6795 pic16_freeAsmop(result,NULL,ic,TRUE);
6798 /*-----------------------------------------------------------------*/
6799 /* genOr - code for or */
6800 /*-----------------------------------------------------------------*/
6801 static void genOr (iCode *ic, iCode *ifx)
6803 operand *left, *right, *result;
6805 unsigned long lit = 0L;
6807 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6809 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6810 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6811 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6813 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6815 /* if left is a literal & right is not then exchange them */
6816 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6817 AOP_NEEDSACC(left)) {
6818 operand *tmp = right ;
6823 /* if result = right then exchange them */
6824 if(pic16_sameRegs(AOP(result),AOP(right))){
6825 operand *tmp = right ;
6830 /* if right is bit then exchange them */
6831 if (AOP_TYPE(right) == AOP_CRY &&
6832 AOP_TYPE(left) != AOP_CRY){
6833 operand *tmp = right ;
6838 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6840 if(AOP_TYPE(right) == AOP_LIT)
6841 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6843 size = AOP_SIZE(result);
6847 if (AOP_TYPE(left) == AOP_CRY){
6848 if(AOP_TYPE(right) == AOP_LIT){
6849 // c = bit & literal;
6851 // lit != 0 => result = 1
6852 if(AOP_TYPE(result) == AOP_CRY){
6854 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6855 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6856 // AOP(result)->aopu.aop_dir,
6857 // AOP(result)->aopu.aop_dir);
6859 continueIfTrue(ifx);
6863 // lit == 0 => result = left
6864 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6866 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6869 if (AOP_TYPE(right) == AOP_CRY){
6870 if(pic16_sameRegs(AOP(result),AOP(left))){
6872 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6873 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6874 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6876 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6877 AOP(result)->aopu.aop_dir,
6878 AOP(result)->aopu.aop_dir);
6879 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6880 AOP(right)->aopu.aop_dir,
6881 AOP(right)->aopu.aop_dir);
6882 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6883 AOP(result)->aopu.aop_dir,
6884 AOP(result)->aopu.aop_dir);
6886 if( AOP_TYPE(result) == AOP_ACC) {
6887 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6888 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6889 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6890 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6894 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6895 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6896 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6897 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6899 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6900 AOP(result)->aopu.aop_dir,
6901 AOP(result)->aopu.aop_dir);
6902 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6903 AOP(right)->aopu.aop_dir,
6904 AOP(right)->aopu.aop_dir);
6905 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6906 AOP(left)->aopu.aop_dir,
6907 AOP(left)->aopu.aop_dir);
6908 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6909 AOP(result)->aopu.aop_dir,
6910 AOP(result)->aopu.aop_dir);
6915 symbol *tlbl = newiTempLabel(NULL);
6916 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6919 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6920 if( AOP_TYPE(right) == AOP_ACC) {
6921 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6923 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6924 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6929 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6930 pic16_emitcode(";XXX setb","c");
6931 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6932 AOP(left)->aopu.aop_dir,tlbl->key+100);
6933 pic16_toBoolean(right);
6934 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6935 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6936 jmpTrueOrFalse(ifx, tlbl);
6940 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6947 pic16_outBitC(result);
6949 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6950 genIfxJump(ifx, "c");
6954 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6955 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6956 if((AOP_TYPE(right) == AOP_LIT) &&
6957 (AOP_TYPE(result) == AOP_CRY) &&
6958 (AOP_TYPE(left) != AOP_CRY)){
6960 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6963 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6965 continueIfTrue(ifx);
6968 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6969 // lit = 0, result = boolean(left)
6971 pic16_emitcode(";XXX setb","c");
6972 pic16_toBoolean(right);
6974 symbol *tlbl = newiTempLabel(NULL);
6975 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6977 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6979 genIfxJump (ifx,"a");
6983 pic16_outBitC(result);
6987 /* if left is same as result */
6988 if(pic16_sameRegs(AOP(result),AOP(left))){
6990 for(;size--; offset++,lit>>=8) {
6991 if(AOP_TYPE(right) == AOP_LIT){
6992 if((lit & 0xff) == 0)
6993 /* or'ing with 0 has no effect */
6996 int p = my_powof2(lit & 0xff);
6998 /* only one bit is set in the literal, so use a bsf instruction */
6999 pic16_emitpcode(POC_BSF,
7000 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7002 if(know_W != (lit & 0xff))
7003 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7004 know_W = lit & 0xff;
7005 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7010 if (AOP_TYPE(left) == AOP_ACC) {
7011 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7012 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7014 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7015 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7017 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7018 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7024 // left & result in different registers
7025 if(AOP_TYPE(result) == AOP_CRY){
7027 // if(size), result in bit
7028 // if(!size && ifx), conditional oper: if(left | right)
7029 symbol *tlbl = newiTempLabel(NULL);
7030 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7031 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7035 pic16_emitcode(";XXX setb","c");
7037 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7038 pic16_emitcode(";XXX orl","a,%s",
7039 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7040 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7045 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7046 pic16_outBitC(result);
7048 jmpTrueOrFalse(ifx, tlbl);
7049 } else for(;(size--);offset++){
7051 // result = left & right
7052 if(AOP_TYPE(right) == AOP_LIT){
7053 int t = (lit >> (offset*8)) & 0x0FFL;
7056 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7057 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7059 pic16_emitcode("movf","%s,w",
7060 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7061 pic16_emitcode("movwf","%s",
7062 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7065 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7066 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7067 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7069 pic16_emitcode("movlw","0x%x",t);
7070 pic16_emitcode("iorwf","%s,w",
7071 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7072 pic16_emitcode("movwf","%s",
7073 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7079 // faster than result <- left, anl result,right
7080 // and better if result is SFR
7081 if (AOP_TYPE(left) == AOP_ACC) {
7082 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7083 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7085 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7086 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7088 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7089 pic16_emitcode("iorwf","%s,w",
7090 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7092 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7093 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7098 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7099 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7100 pic16_freeAsmop(result,NULL,ic,TRUE);
7103 /*-----------------------------------------------------------------*/
7104 /* genXor - code for xclusive or */
7105 /*-----------------------------------------------------------------*/
7106 static void genXor (iCode *ic, iCode *ifx)
7108 operand *left, *right, *result;
7110 unsigned long lit = 0L;
7112 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7114 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7115 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7116 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7118 /* if left is a literal & right is not ||
7119 if left needs acc & right does not */
7120 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7121 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7122 operand *tmp = right ;
7127 /* if result = right then exchange them */
7128 if(pic16_sameRegs(AOP(result),AOP(right))){
7129 operand *tmp = right ;
7134 /* if right is bit then exchange them */
7135 if (AOP_TYPE(right) == AOP_CRY &&
7136 AOP_TYPE(left) != AOP_CRY){
7137 operand *tmp = right ;
7141 if(AOP_TYPE(right) == AOP_LIT)
7142 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7144 size = AOP_SIZE(result);
7148 if (AOP_TYPE(left) == AOP_CRY){
7149 if(AOP_TYPE(right) == AOP_LIT){
7150 // c = bit & literal;
7152 // lit>>1 != 0 => result = 1
7153 if(AOP_TYPE(result) == AOP_CRY){
7155 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
7156 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7158 continueIfTrue(ifx);
7161 pic16_emitcode("setb","c");
7165 // lit == 0, result = left
7166 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7168 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7170 // lit == 1, result = not(left)
7171 if(size && pic16_sameRegs(AOP(result),AOP(left))){
7172 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
7173 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
7174 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7177 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7178 pic16_emitcode("cpl","c");
7185 symbol *tlbl = newiTempLabel(NULL);
7186 if (AOP_TYPE(right) == AOP_CRY){
7188 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7191 int sizer = AOP_SIZE(right);
7193 // if val>>1 != 0, result = 1
7194 pic16_emitcode("setb","c");
7196 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7198 // test the msb of the lsb
7199 pic16_emitcode("anl","a,#0xfe");
7200 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7204 pic16_emitcode("rrc","a");
7206 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7207 pic16_emitcode("cpl","c");
7208 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7213 pic16_outBitC(result);
7215 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7216 genIfxJump(ifx, "c");
7220 if(pic16_sameRegs(AOP(result),AOP(left))){
7221 /* if left is same as result */
7222 for(;size--; offset++) {
7223 if(AOP_TYPE(right) == AOP_LIT){
7224 int t = (lit >> (offset*8)) & 0x0FFL;
7228 if (IS_AOP_PREG(left)) {
7229 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7230 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7231 pic16_aopPut(AOP(result),"a",offset);
7233 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7234 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7235 pic16_emitcode("xrl","%s,%s",
7236 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7237 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7240 if (AOP_TYPE(left) == AOP_ACC)
7241 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7243 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7244 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7246 if (IS_AOP_PREG(left)) {
7247 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7248 pic16_aopPut(AOP(result),"a",offset);
7250 pic16_emitcode("xrl","%s,a",
7251 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7257 // left & result in different registers
7258 if(AOP_TYPE(result) == AOP_CRY){
7260 // if(size), result in bit
7261 // if(!size && ifx), conditional oper: if(left ^ right)
7262 symbol *tlbl = newiTempLabel(NULL);
7263 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7265 pic16_emitcode("setb","c");
7267 if((AOP_TYPE(right) == AOP_LIT) &&
7268 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7269 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7271 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7272 pic16_emitcode("xrl","a,%s",
7273 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7275 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7280 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7281 pic16_outBitC(result);
7283 jmpTrueOrFalse(ifx, tlbl);
7284 } else for(;(size--);offset++){
7286 // result = left & right
7287 if(AOP_TYPE(right) == AOP_LIT){
7288 int t = (lit >> (offset*8)) & 0x0FFL;
7291 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7292 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7293 pic16_emitcode("movf","%s,w",
7294 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7295 pic16_emitcode("movwf","%s",
7296 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7299 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7300 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7301 pic16_emitcode("comf","%s,w",
7302 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7303 pic16_emitcode("movwf","%s",
7304 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7307 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7308 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7309 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7310 pic16_emitcode("movlw","0x%x",t);
7311 pic16_emitcode("xorwf","%s,w",
7312 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7313 pic16_emitcode("movwf","%s",
7314 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7320 // faster than result <- left, anl result,right
7321 // and better if result is SFR
7322 if (AOP_TYPE(left) == AOP_ACC) {
7323 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7324 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7326 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7327 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7328 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7329 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7331 if ( AOP_TYPE(result) != AOP_ACC){
7332 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7333 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7339 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7340 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7341 pic16_freeAsmop(result,NULL,ic,TRUE);
7344 /*-----------------------------------------------------------------*/
7345 /* genInline - write the inline code out */
7346 /*-----------------------------------------------------------------*/
7347 static void genInline (iCode *ic)
7349 char *buffer, *bp, *bp1;
7351 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7353 _G.inLine += (!options.asmpeep);
7355 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7356 strcpy(buffer,IC_INLINE(ic));
7358 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7360 /* emit each line as a code */
7366 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7374 /* print label, use this special format with NULL directive
7375 * to denote that the argument should not be indented with tab */
7376 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7383 if ((bp1 != bp) && *bp1)
7384 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7389 _G.inLine -= (!options.asmpeep);
7392 /*-----------------------------------------------------------------*/
7393 /* genRRC - rotate right with carry */
7394 /*-----------------------------------------------------------------*/
7395 static void genRRC (iCode *ic)
7397 operand *left , *result ;
7398 int size, offset = 0, same;
7400 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7402 /* rotate right with carry */
7404 result=IC_RESULT(ic);
7405 pic16_aopOp (left,ic,FALSE);
7406 pic16_aopOp (result,ic,FALSE);
7408 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7410 same = pic16_sameRegs(AOP(result),AOP(left));
7412 size = AOP_SIZE(result);
7414 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7416 /* get the lsb and put it into the carry */
7417 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7424 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7426 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7427 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7433 pic16_freeAsmop(left,NULL,ic,TRUE);
7434 pic16_freeAsmop(result,NULL,ic,TRUE);
7437 /*-----------------------------------------------------------------*/
7438 /* genRLC - generate code for rotate left with carry */
7439 /*-----------------------------------------------------------------*/
7440 static void genRLC (iCode *ic)
7442 operand *left , *result ;
7443 int size, offset = 0;
7446 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7447 /* rotate right with carry */
7449 result=IC_RESULT(ic);
7450 pic16_aopOp (left,ic,FALSE);
7451 pic16_aopOp (result,ic,FALSE);
7453 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7455 same = pic16_sameRegs(AOP(result),AOP(left));
7457 /* move it to the result */
7458 size = AOP_SIZE(result);
7460 /* get the msb and put it into the carry */
7461 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7468 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7470 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7471 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7478 pic16_freeAsmop(left,NULL,ic,TRUE);
7479 pic16_freeAsmop(result,NULL,ic,TRUE);
7483 /* gpasm can get the highest order bit with HIGH/UPPER
7484 * so the following probably is not needed -- VR */
7486 /*-----------------------------------------------------------------*/
7487 /* genGetHbit - generates code get highest order bit */
7488 /*-----------------------------------------------------------------*/
7489 static void genGetHbit (iCode *ic)
7491 operand *left, *result;
7493 result=IC_RESULT(ic);
7494 pic16_aopOp (left,ic,FALSE);
7495 pic16_aopOp (result,ic,FALSE);
7497 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7498 /* get the highest order byte into a */
7499 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7500 if(AOP_TYPE(result) == AOP_CRY){
7501 pic16_emitcode("rlc","a");
7502 pic16_outBitC(result);
7505 pic16_emitcode("rl","a");
7506 pic16_emitcode("anl","a,#0x01");
7507 pic16_outAcc(result);
7511 pic16_freeAsmop(left,NULL,ic,TRUE);
7512 pic16_freeAsmop(result,NULL,ic,TRUE);
7516 /*-----------------------------------------------------------------*/
7517 /* AccRol - rotate left accumulator by known count */
7518 /*-----------------------------------------------------------------*/
7519 static void AccRol (int shCount)
7521 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7522 shCount &= 0x0007; // shCount : 0..7
7527 pic16_emitcode("rl","a");
7530 pic16_emitcode("rl","a");
7531 pic16_emitcode("rl","a");
7534 pic16_emitcode("swap","a");
7535 pic16_emitcode("rr","a");
7538 pic16_emitcode("swap","a");
7541 pic16_emitcode("swap","a");
7542 pic16_emitcode("rl","a");
7545 pic16_emitcode("rr","a");
7546 pic16_emitcode("rr","a");
7549 pic16_emitcode("rr","a");
7555 /*-----------------------------------------------------------------*/
7556 /* AccLsh - left shift accumulator by known count */
7557 /*-----------------------------------------------------------------*/
7558 static void AccLsh (int shCount)
7560 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7566 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7569 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7570 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7573 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7574 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7577 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7580 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7581 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7584 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7585 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7588 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7592 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7595 /*-----------------------------------------------------------------*/
7596 /* AccRsh - right shift accumulator by known count */
7597 /*-----------------------------------------------------------------*/
7598 static void AccRsh (int shCount, int andmask)
7600 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7605 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7606 // andmask = 0; /* no need */
7609 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7610 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7611 // andmask = 0; /* no need */
7614 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7615 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7618 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7621 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7622 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7625 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7626 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7629 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7634 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7636 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7640 /*-----------------------------------------------------------------*/
7641 /* AccSRsh - signed right shift accumulator by known count */
7642 /*-----------------------------------------------------------------*/
7643 static void AccSRsh (int shCount)
7646 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7649 pic16_emitcode("mov","c,acc.7");
7650 pic16_emitcode("rrc","a");
7651 } else if(shCount == 2){
7652 pic16_emitcode("mov","c,acc.7");
7653 pic16_emitcode("rrc","a");
7654 pic16_emitcode("mov","c,acc.7");
7655 pic16_emitcode("rrc","a");
7657 tlbl = newiTempLabel(NULL);
7658 /* rotate right accumulator */
7659 AccRol(8 - shCount);
7660 /* and kill the higher order bits */
7661 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7662 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7663 pic16_emitcode("orl","a,#0x%02x",
7664 (unsigned char)~SRMask[shCount]);
7665 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7670 /*-----------------------------------------------------------------*/
7671 /* shiftR1Left2Result - shift right one byte from left to result */
7672 /*-----------------------------------------------------------------*/
7673 static void shiftR1Left2ResultSigned (operand *left, int offl,
7674 operand *result, int offr,
7679 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7681 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7685 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7687 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7689 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7690 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7696 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7698 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7700 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7701 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7703 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7704 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7710 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7712 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7713 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7716 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7717 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7718 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7720 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7721 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7723 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7727 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7728 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7729 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7730 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
7731 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7735 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7737 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7738 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7740 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7741 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
7742 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7743 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
7744 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7749 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7750 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7751 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7752 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7753 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7754 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7756 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7757 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7758 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7759 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7760 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7766 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7767 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7768 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7769 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7771 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7772 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7773 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7781 /*-----------------------------------------------------------------*/
7782 /* shiftR1Left2Result - shift right one byte from left to result */
7783 /*-----------------------------------------------------------------*/
7784 static void shiftR1Left2Result (operand *left, int offl,
7785 operand *result, int offr,
7786 int shCount, int sign)
7790 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7792 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7794 /* Copy the msb into the carry if signed. */
7796 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7806 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7808 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7809 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7815 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7817 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7818 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7821 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7826 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7828 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7829 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7832 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7833 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7834 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7835 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7839 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7840 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7841 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7845 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7846 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7847 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7849 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7854 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7855 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7856 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7857 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7858 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7863 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7864 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7865 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7874 /*-----------------------------------------------------------------*/
7875 /* shiftL1Left2Result - shift left one byte from left to result */
7876 /*-----------------------------------------------------------------*/
7877 static void shiftL1Left2Result (operand *left, int offl,
7878 operand *result, int offr, int shCount)
7883 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7885 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7886 DEBUGpic16_emitcode ("; ***","same = %d",same);
7887 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7889 /* shift left accumulator */
7890 //AccLsh(shCount); // don't comment out just yet...
7891 // pic16_aopPut(AOP(result),"a",offr);
7895 /* Shift left 1 bit position */
7896 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7898 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7900 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7901 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7905 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7906 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7907 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7908 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7911 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7912 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7913 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7914 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7915 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7918 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7919 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7920 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7923 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7924 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7925 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7926 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7929 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7930 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7931 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7932 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7933 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7936 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7937 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7938 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7942 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7947 /*-----------------------------------------------------------------*/
7948 /* movLeft2Result - move byte from left to result */
7949 /*-----------------------------------------------------------------*/
7950 static void movLeft2Result (operand *left, int offl,
7951 operand *result, int offr)
7954 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7955 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7956 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7958 if (*l == '@' && (IS_AOP_PREG(result))) {
7959 pic16_emitcode("mov","a,%s",l);
7960 pic16_aopPut(AOP(result),"a",offr);
7962 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7963 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7968 /*-----------------------------------------------------------------*/
7969 /* shiftL2Left2Result - shift left two bytes from left to result */
7970 /*-----------------------------------------------------------------*/
7971 static void shiftL2Left2Result (operand *left, int offl,
7972 operand *result, int offr, int shCount)
7974 int same = pic16_sameRegs(AOP(result), AOP(left));
7977 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7979 if (same && (offl != offr)) { // shift bytes
7982 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7983 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7985 } else { // just treat as different later on
7998 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7999 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8000 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8004 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8005 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8011 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8012 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8013 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8014 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8015 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8016 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8017 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8019 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8020 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8024 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8025 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8026 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8027 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8028 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8029 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8030 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8031 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8032 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8033 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8036 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8037 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8038 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8039 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8040 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8050 /* note, use a mov/add for the shift since the mov has a
8051 chance of getting optimized out */
8052 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8053 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8054 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8055 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8056 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8060 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8061 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8067 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8068 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8069 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8070 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8071 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8072 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8073 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8074 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8078 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8079 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8083 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8084 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8085 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8086 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8088 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8089 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8090 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8091 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8092 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8093 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8094 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8095 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8098 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8099 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8100 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8101 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8102 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8107 /*-----------------------------------------------------------------*/
8108 /* shiftR2Left2Result - shift right two bytes from left to result */
8109 /*-----------------------------------------------------------------*/
8110 static void shiftR2Left2Result (operand *left, int offl,
8111 operand *result, int offr,
8112 int shCount, int sign)
8114 int same = pic16_sameRegs(AOP(result), AOP(left));
8116 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8118 if (same && (offl != offr)) { // shift right bytes
8121 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8122 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8124 } else { // just treat as different later on
8136 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8141 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8142 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8144 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8145 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8146 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8147 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8152 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8155 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8156 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8163 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
8164 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
8165 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8167 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8168 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
8169 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8170 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8172 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8173 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8174 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8176 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8177 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8178 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8179 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8180 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8184 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8185 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8189 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
8190 pic16_emitpcode(POC_BTFSC,
8191 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
8192 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8200 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8201 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8203 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8204 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8205 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8206 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8208 pic16_emitpcode(POC_BTFSC,
8209 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8210 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8212 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8213 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8214 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8215 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8217 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8218 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8219 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8220 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8221 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8222 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8223 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8224 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8226 pic16_emitpcode(POC_BTFSC,
8227 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8228 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8230 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8231 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8238 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8239 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8240 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8241 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8244 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8246 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8251 /*-----------------------------------------------------------------*/
8252 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8253 /*-----------------------------------------------------------------*/
8254 static void shiftLLeftOrResult (operand *left, int offl,
8255 operand *result, int offr, int shCount)
8257 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8259 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8260 /* shift left accumulator */
8262 /* or with result */
8263 /* back to result */
8264 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8267 /*-----------------------------------------------------------------*/
8268 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8269 /*-----------------------------------------------------------------*/
8270 static void shiftRLeftOrResult (operand *left, int offl,
8271 operand *result, int offr, int shCount)
8273 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8275 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8276 /* shift right accumulator */
8278 /* or with result */
8279 /* back to result */
8280 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8283 /*-----------------------------------------------------------------*/
8284 /* genlshOne - left shift a one byte quantity by known count */
8285 /*-----------------------------------------------------------------*/
8286 static void genlshOne (operand *result, operand *left, int shCount)
8288 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8289 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8292 /*-----------------------------------------------------------------*/
8293 /* genlshTwo - left shift two bytes by known amount != 0 */
8294 /*-----------------------------------------------------------------*/
8295 static void genlshTwo (operand *result,operand *left, int shCount)
8299 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8300 size = pic16_getDataSize(result);
8302 /* if shCount >= 8 */
8308 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8310 movLeft2Result(left, LSB, result, MSB16);
8312 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8315 /* 1 <= shCount <= 7 */
8318 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8320 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8324 /*-----------------------------------------------------------------*/
8325 /* shiftLLong - shift left one long from left to result */
8326 /* offr = LSB or MSB16 */
8327 /*-----------------------------------------------------------------*/
8328 static void shiftLLong (operand *left, operand *result, int offr )
8330 int size = AOP_SIZE(result);
8331 int same = pic16_sameRegs(AOP(left),AOP(result));
8334 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8336 if (same && (offr == MSB16)) { //shift one byte
8337 for(i=size-1;i>=MSB16;i--) {
8338 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8339 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8342 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8345 if (size >= LSB+offr ){
8347 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8349 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8350 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8354 if(size >= MSB16+offr){
8356 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8358 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8359 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8363 if(size >= MSB24+offr){
8365 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8367 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8368 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8372 if(size > MSB32+offr){
8374 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8376 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8377 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8381 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8385 /*-----------------------------------------------------------------*/
8386 /* genlshFour - shift four byte by a known amount != 0 */
8387 /*-----------------------------------------------------------------*/
8388 static void genlshFour (operand *result, operand *left, int shCount)
8392 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8393 size = AOP_SIZE(result);
8395 /* if shifting more that 3 bytes */
8396 if (shCount >= 24 ) {
8399 /* lowest order of left goes to the highest
8400 order of the destination */
8401 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8403 movLeft2Result(left, LSB, result, MSB32);
8405 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8406 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8407 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8412 /* more than two bytes */
8413 else if ( shCount >= 16 ) {
8414 /* lower order two bytes goes to higher order two bytes */
8416 /* if some more remaining */
8418 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8420 movLeft2Result(left, MSB16, result, MSB32);
8421 movLeft2Result(left, LSB, result, MSB24);
8423 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8424 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8428 /* if more than 1 byte */
8429 else if ( shCount >= 8 ) {
8430 /* lower order three bytes goes to higher order three bytes */
8434 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8436 movLeft2Result(left, LSB, result, MSB16);
8438 else{ /* size = 4 */
8440 movLeft2Result(left, MSB24, result, MSB32);
8441 movLeft2Result(left, MSB16, result, MSB24);
8442 movLeft2Result(left, LSB, result, MSB16);
8443 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8445 else if(shCount == 1)
8446 shiftLLong(left, result, MSB16);
8448 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8449 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8450 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8451 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8456 /* 1 <= shCount <= 7 */
8457 else if(shCount <= 3)
8459 shiftLLong(left, result, LSB);
8460 while(--shCount >= 1)
8461 shiftLLong(result, result, LSB);
8463 /* 3 <= shCount <= 7, optimize */
8465 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8466 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8467 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8471 /*-----------------------------------------------------------------*/
8472 /* genLeftShiftLiteral - left shifting by known count */
8473 /*-----------------------------------------------------------------*/
8474 static void genLeftShiftLiteral (operand *left,
8479 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8482 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8483 pic16_freeAsmop(right,NULL,ic,TRUE);
8485 pic16_aopOp(left,ic,FALSE);
8486 pic16_aopOp(result,ic,FALSE);
8488 size = getSize(operandType(result));
8491 pic16_emitcode("; shift left ","result %d, left %d",size,
8495 /* I suppose that the left size >= result size */
8498 movLeft2Result(left, size, result, size);
8502 else if(shCount >= (size * 8))
8504 pic16_aopPut(AOP(result),zero,size);
8508 genlshOne (result,left,shCount);
8513 genlshTwo (result,left,shCount);
8517 genlshFour (result,left,shCount);
8521 pic16_freeAsmop(left,NULL,ic,TRUE);
8522 pic16_freeAsmop(result,NULL,ic,TRUE);
8525 /*-----------------------------------------------------------------*
8526 * genMultiAsm - repeat assembly instruction for size of register.
8527 * if endian == 1, then the high byte (i.e base address + size of
8528 * register) is used first else the low byte is used first;
8529 *-----------------------------------------------------------------*/
8530 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8548 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
8553 /*-----------------------------------------------------------------*/
8554 /* genLeftShift - generates code for left shifting */
8555 /*-----------------------------------------------------------------*/
8556 static void genLeftShift (iCode *ic)
8558 operand *left,*right, *result;
8561 symbol *tlbl , *tlbl1;
8564 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8566 right = IC_RIGHT(ic);
8568 result = IC_RESULT(ic);
8570 pic16_aopOp(right,ic,FALSE);
8572 /* if the shift count is known then do it
8573 as efficiently as possible */
8574 if (AOP_TYPE(right) == AOP_LIT) {
8575 genLeftShiftLiteral (left,right,result,ic);
8579 /* shift count is unknown then we have to form
8580 a loop get the loop count in B : Note: we take
8581 only the lower order byte since shifting
8582 more that 32 bits make no sense anyway, ( the
8583 largest size of an object can be only 32 bits ) */
8586 pic16_aopOp(left,ic,FALSE);
8587 pic16_aopOp(result,ic,FALSE);
8589 /* now move the left to the result if they are not the
8591 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8592 AOP_SIZE(result) > 1) {
8594 size = AOP_SIZE(result);
8597 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8598 if (*l == '@' && (IS_AOP_PREG(result))) {
8600 pic16_emitcode("mov","a,%s",l);
8601 pic16_aopPut(AOP(result),"a",offset);
8603 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8604 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8605 //pic16_aopPut(AOP(result),l,offset);
8611 size = AOP_SIZE(result);
8613 /* if it is only one byte then */
8615 if(optimized_for_speed) {
8616 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8617 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8618 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8619 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8620 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8621 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8622 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8623 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
8624 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
8625 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
8626 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8627 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8630 tlbl = newiTempLabel(NULL);
8631 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8632 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8633 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8636 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8637 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8638 pic16_emitpLabel(tlbl->key);
8639 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8640 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8642 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8647 if (pic16_sameRegs(AOP(left),AOP(result))) {
8649 tlbl = newiTempLabel(NULL);
8650 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8651 genMultiAsm(POC_RRCF, result, size,1);
8652 pic16_emitpLabel(tlbl->key);
8653 genMultiAsm(POC_RLCF, result, size,0);
8654 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8656 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8660 //tlbl = newiTempLabel(NULL);
8662 //tlbl1 = newiTempLabel(NULL);
8664 //reAdjustPreg(AOP(result));
8666 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8667 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8668 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8670 //pic16_emitcode("add","a,acc");
8671 //pic16_aopPut(AOP(result),"a",offset++);
8673 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8675 // pic16_emitcode("rlc","a");
8676 // pic16_aopPut(AOP(result),"a",offset++);
8678 //reAdjustPreg(AOP(result));
8680 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8681 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8684 tlbl = newiTempLabel(NULL);
8685 tlbl1= newiTempLabel(NULL);
8687 size = AOP_SIZE(result);
8690 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8692 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8694 /* offset should be 0, 1 or 3 */
8696 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8698 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8700 pic16_emitpcode(POC_MOVWF, pctemp);
8703 pic16_emitpLabel(tlbl->key);
8706 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8708 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
8710 pic16_emitpcode(POC_DECFSZ, pctemp);
8711 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8712 pic16_emitpLabel(tlbl1->key);
8714 pic16_popReleaseTempReg(pctemp);
8718 pic16_freeAsmop (right,NULL,ic,TRUE);
8719 pic16_freeAsmop(left,NULL,ic,TRUE);
8720 pic16_freeAsmop(result,NULL,ic,TRUE);
8723 /*-----------------------------------------------------------------*/
8724 /* genrshOne - right shift a one byte quantity by known count */
8725 /*-----------------------------------------------------------------*/
8726 static void genrshOne (operand *result, operand *left,
8727 int shCount, int sign)
8729 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8730 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8733 /*-----------------------------------------------------------------*/
8734 /* genrshTwo - right shift two bytes by known amount != 0 */
8735 /*-----------------------------------------------------------------*/
8736 static void genrshTwo (operand *result,operand *left,
8737 int shCount, int sign)
8739 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8740 /* if shCount >= 8 */
8744 shiftR1Left2Result(left, MSB16, result, LSB,
8747 movLeft2Result(left, MSB16, result, LSB);
8749 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8752 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8753 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8757 /* 1 <= shCount <= 7 */
8759 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
8762 /*-----------------------------------------------------------------*/
8763 /* shiftRLong - shift right one long from left to result */
8764 /* offl = LSB or MSB16 */
8765 /*-----------------------------------------------------------------*/
8766 static void shiftRLong (operand *left, int offl,
8767 operand *result, int sign)
8769 int size = AOP_SIZE(result);
8770 int same = pic16_sameRegs(AOP(left),AOP(result));
8772 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8774 if (same && (offl == MSB16)) { //shift one byte right
8775 for(i=MSB16;i<size;i++) {
8776 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8777 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8782 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8788 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8790 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8791 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8795 /* add sign of "a" */
8796 pic16_addSign(result, MSB32, sign);
8800 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8802 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8803 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8807 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8809 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8810 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8814 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8817 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8818 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8823 /*-----------------------------------------------------------------*/
8824 /* genrshFour - shift four byte by a known amount != 0 */
8825 /*-----------------------------------------------------------------*/
8826 static void genrshFour (operand *result, operand *left,
8827 int shCount, int sign)
8829 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8830 /* if shifting more that 3 bytes */
8831 if(shCount >= 24 ) {
8834 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8836 movLeft2Result(left, MSB32, result, LSB);
8838 pic16_addSign(result, MSB16, sign);
8840 else if(shCount >= 16){
8843 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8845 movLeft2Result(left, MSB24, result, LSB);
8846 movLeft2Result(left, MSB32, result, MSB16);
8848 pic16_addSign(result, MSB24, sign);
8850 else if(shCount >= 8){
8853 shiftRLong(left, MSB16, result, sign);
8854 else if(shCount == 0){
8855 movLeft2Result(left, MSB16, result, LSB);
8856 movLeft2Result(left, MSB24, result, MSB16);
8857 movLeft2Result(left, MSB32, result, MSB24);
8858 pic16_addSign(result, MSB32, sign);
8860 else{ //shcount >= 2
8861 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8862 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8863 /* the last shift is signed */
8864 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8865 pic16_addSign(result, MSB32, sign);
8868 else{ /* 1 <= shCount <= 7 */
8870 shiftRLong(left, LSB, result, sign);
8872 shiftRLong(result, LSB, result, sign);
8875 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8876 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8877 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8882 /*-----------------------------------------------------------------*/
8883 /* genRightShiftLiteral - right shifting by known count */
8884 /*-----------------------------------------------------------------*/
8885 static void genRightShiftLiteral (operand *left,
8891 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8894 pic16_freeAsmop(right,NULL,ic,TRUE);
8896 pic16_aopOp(left,ic,FALSE);
8897 pic16_aopOp(result,ic,FALSE);
8899 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8902 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8906 lsize = pic16_getDataSize(left);
8907 res_size = pic16_getDataSize(result);
8908 /* test the LEFT size !!! */
8910 /* I suppose that the left size >= result size */
8913 movLeft2Result(left, lsize, result, res_size);
8916 else if(shCount >= (lsize * 8)){
8919 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8921 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8922 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8927 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8928 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8929 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8931 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8936 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8943 genrshOne (result,left,shCount,sign);
8947 genrshTwo (result,left,shCount,sign);
8951 genrshFour (result,left,shCount,sign);
8959 pic16_freeAsmop(left,NULL,ic,TRUE);
8960 pic16_freeAsmop(result,NULL,ic,TRUE);
8963 /*-----------------------------------------------------------------*/
8964 /* genSignedRightShift - right shift of signed number */
8965 /*-----------------------------------------------------------------*/
8966 static void genSignedRightShift (iCode *ic)
8968 operand *right, *left, *result;
8971 symbol *tlbl, *tlbl1 ;
8974 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8976 /* we do it the hard way put the shift count in b
8977 and loop thru preserving the sign */
8978 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8980 right = IC_RIGHT(ic);
8982 result = IC_RESULT(ic);
8984 pic16_aopOp(right,ic,FALSE);
8985 pic16_aopOp(left,ic,FALSE);
8986 pic16_aopOp(result,ic,FALSE);
8989 if ( AOP_TYPE(right) == AOP_LIT) {
8990 genRightShiftLiteral (left,right,result,ic,1);
8993 /* shift count is unknown then we have to form
8994 a loop get the loop count in B : Note: we take
8995 only the lower order byte since shifting
8996 more that 32 bits make no sense anyway, ( the
8997 largest size of an object can be only 32 bits ) */
8999 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9000 //pic16_emitcode("inc","b");
9001 //pic16_freeAsmop (right,NULL,ic,TRUE);
9002 //pic16_aopOp(left,ic,FALSE);
9003 //pic16_aopOp(result,ic,FALSE);
9005 /* now move the left to the result if they are not the
9007 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9008 AOP_SIZE(result) > 1) {
9010 size = AOP_SIZE(result);
9014 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9015 if (*l == '@' && IS_AOP_PREG(result)) {
9017 pic16_emitcode("mov","a,%s",l);
9018 pic16_aopPut(AOP(result),"a",offset);
9020 pic16_aopPut(AOP(result),l,offset);
9022 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
9023 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9029 /* mov the highest order bit to OVR */
9030 tlbl = newiTempLabel(NULL);
9031 tlbl1= newiTempLabel(NULL);
9033 size = AOP_SIZE(result);
9036 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
9038 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9040 /* offset should be 0, 1 or 3 */
9041 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
9043 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9045 pic16_emitpcode(POC_MOVWF, pctemp);
9048 pic16_emitpLabel(tlbl->key);
9050 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
9051 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
9054 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
9057 pic16_emitpcode(POC_DECFSZ, pctemp);
9058 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9059 pic16_emitpLabel(tlbl1->key);
9061 pic16_popReleaseTempReg(pctemp);
9063 size = AOP_SIZE(result);
9065 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
9066 pic16_emitcode("rlc","a");
9067 pic16_emitcode("mov","ov,c");
9068 /* if it is only one byte then */
9070 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9072 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9073 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9074 pic16_emitcode("mov","c,ov");
9075 pic16_emitcode("rrc","a");
9076 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9077 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9078 pic16_aopPut(AOP(result),"a",0);
9082 reAdjustPreg(AOP(result));
9083 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9084 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9085 pic16_emitcode("mov","c,ov");
9087 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9089 pic16_emitcode("rrc","a");
9090 pic16_aopPut(AOP(result),"a",offset--);
9092 reAdjustPreg(AOP(result));
9093 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9094 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9099 pic16_freeAsmop(left,NULL,ic,TRUE);
9100 pic16_freeAsmop(result,NULL,ic,TRUE);
9101 pic16_freeAsmop(right,NULL,ic,TRUE);
9104 /*-----------------------------------------------------------------*/
9105 /* genRightShift - generate code for right shifting */
9106 /*-----------------------------------------------------------------*/
9107 static void genRightShift (iCode *ic)
9109 operand *right, *left, *result;
9113 symbol *tlbl, *tlbl1 ;
9115 /* if signed then we do it the hard way preserve the
9116 sign bit moving it inwards */
9117 letype = getSpec(operandType(IC_LEFT(ic)));
9118 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9120 if (!SPEC_USIGN(letype)) {
9121 genSignedRightShift (ic);
9125 /* signed & unsigned types are treated the same : i.e. the
9126 signed is NOT propagated inwards : quoting from the
9127 ANSI - standard : "for E1 >> E2, is equivalent to division
9128 by 2**E2 if unsigned or if it has a non-negative value,
9129 otherwise the result is implementation defined ", MY definition
9130 is that the sign does not get propagated */
9132 right = IC_RIGHT(ic);
9134 result = IC_RESULT(ic);
9136 pic16_aopOp(right,ic,FALSE);
9138 /* if the shift count is known then do it
9139 as efficiently as possible */
9140 if (AOP_TYPE(right) == AOP_LIT) {
9141 genRightShiftLiteral (left,right,result,ic, 0);
9145 /* shift count is unknown then we have to form
9146 a loop get the loop count in B : Note: we take
9147 only the lower order byte since shifting
9148 more that 32 bits make no sense anyway, ( the
9149 largest size of an object can be only 32 bits ) */
9151 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9152 pic16_emitcode("inc","b");
9153 pic16_aopOp(left,ic,FALSE);
9154 pic16_aopOp(result,ic,FALSE);
9156 /* now move the left to the result if they are not the
9158 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9159 AOP_SIZE(result) > 1) {
9161 size = AOP_SIZE(result);
9164 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9165 if (*l == '@' && IS_AOP_PREG(result)) {
9167 pic16_emitcode("mov","a,%s",l);
9168 pic16_aopPut(AOP(result),"a",offset);
9170 pic16_aopPut(AOP(result),l,offset);
9175 tlbl = newiTempLabel(NULL);
9176 tlbl1= newiTempLabel(NULL);
9177 size = AOP_SIZE(result);
9180 /* if it is only one byte then */
9183 tlbl = newiTempLabel(NULL);
9184 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9185 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9186 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9189 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9190 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9191 pic16_emitpLabel(tlbl->key);
9192 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9193 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9195 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9200 reAdjustPreg(AOP(result));
9201 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9202 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9205 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9207 pic16_emitcode("rrc","a");
9208 pic16_aopPut(AOP(result),"a",offset--);
9210 reAdjustPreg(AOP(result));
9212 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9213 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9216 pic16_freeAsmop(left,NULL,ic,TRUE);
9217 pic16_freeAsmop (right,NULL,ic,TRUE);
9218 pic16_freeAsmop(result,NULL,ic,TRUE);
9222 void pic16_loadFSR0(operand *op)
9224 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9227 /*-----------------------------------------------------------------*/
9228 /* genUnpackBits - generates code for unpacking bits */
9229 /*-----------------------------------------------------------------*/
9230 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
9237 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9238 etype = getSpec(operandType(result));
9240 /* the following call to pic16_loadFSR0 is temporary until
9241 * optimization to handle single bit assignments is added
9242 * to the function. Until then use the old safe way! -- VR */
9243 pic16_loadFSR0( left );
9245 /* read the first byte */
9252 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9255 pic16_emitcode("clr","a");
9256 pic16_emitcode("movc","a","@a+dptr");
9261 /* if we have bitdisplacement then it fits */
9262 /* into this byte completely or if length is */
9263 /* less than a byte */
9264 if ((shCnt = SPEC_BSTR(etype)) ||
9265 (SPEC_BLEN(etype) <= 8)) {
9267 /* shift right acc */
9270 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9271 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9273 /* VR -- normally I would use the following, but since we use the hack,
9274 * to avoid the masking from AccRsh, why not mask it right now? */
9277 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9280 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9286 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9287 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9290 /* bit field did not fit in a byte */
9291 rlen = SPEC_BLEN(etype) - 8;
9292 pic16_aopPut(AOP(result),"a",offset++);
9299 pic16_emitcode("inc","%s",rname);
9300 pic16_emitcode("mov","a,@%s",rname);
9304 pic16_emitcode("inc","%s",rname);
9305 pic16_emitcode("movx","a,@%s",rname);
9309 pic16_emitcode("inc","dptr");
9310 pic16_emitcode("movx","a,@dptr");
9314 pic16_emitcode("clr","a");
9315 pic16_emitcode("inc","dptr");
9316 pic16_emitcode("movc","a","@a+dptr");
9320 pic16_emitcode("inc","dptr");
9321 pic16_emitcode("lcall","__gptrget");
9326 /* if we are done */
9330 pic16_aopPut(AOP(result),"a",offset++);
9335 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9336 pic16_aopPut(AOP(result),"a",offset);
9343 static void genDataPointerGet(operand *left,
9347 int size, offset = 0, leoffset=0 ;
9349 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9350 pic16_aopOp(result, ic, FALSE);
9352 size = AOP_SIZE(result);
9353 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9357 /* The following tests may save a redudant movff instruction when
9358 * accessing unions */
9360 /* if they are the same */
9361 if (operandsEqu (left, result)) {
9362 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9368 /* if they are the same registers */
9369 if (pic16_sameRegs(AOP(left),AOP(result))) {
9370 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9376 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9377 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9378 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9385 if ( AOP_TYPE(left) == AOP_PCODE) {
9386 fprintf(stderr,"genDataPointerGet %s, %d\n",
9387 AOP(left)->aopu.pcop->name,
9388 (AOP(left)->aopu.pcop->type == PO_DIR)?
9389 PCOR(AOP(left)->aopu.pcop)->instance:
9390 PCOI(AOP(left)->aopu.pcop)->offset);
9394 if(AOP(left)->aopu.pcop->type == PO_DIR)
9395 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9397 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9400 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9402 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9403 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9404 mov2w(AOP(left), offset); // patch 8
9405 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9407 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9408 pic16_popGet(AOP(left), offset), //patch 8
9409 pic16_popGet(AOP(result), offset)));
9417 pic16_freeAsmop(result,NULL,ic,TRUE);
9422 /*-----------------------------------------------------------------*/
9423 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
9424 /*-----------------------------------------------------------------*/
9425 static void genNearPointerGet (operand *left,
9430 //regs *preg = NULL ;
9431 sym_link *rtype, *retype;
9432 sym_link *ltype = operandType(left);
9434 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9435 rtype = operandType(result);
9436 retype= getSpec(rtype);
9438 pic16_aopOp(left,ic,FALSE);
9440 // pic16_DumpOp("(left)",left);
9441 // pic16_DumpOp("(result)",result);
9443 /* if left is rematerialisable and
9444 * result is not bit variable type and
9445 * the left is pointer to data space i.e
9446 * lower 128 bytes of space */
9447 if (AOP_TYPE(left) == AOP_PCODE
9448 && !IS_BITFIELD(retype)
9449 && DCL_TYPE(ltype) == POINTER) {
9451 genDataPointerGet (left,result,ic);
9452 pic16_freeAsmop(left, NULL, ic, TRUE);
9456 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9458 /* if the value is already in a pointer register
9459 * then don't need anything more */
9460 if (!AOP_INPREG(AOP(left))) {
9461 /* otherwise get a free pointer register */
9462 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9464 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9465 if( (AOP_TYPE(left) == AOP_PCODE)
9466 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9467 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9469 if(!IS_BITFIELD(retype))
9470 pic16_loadFSR0( left ); // patch 10
9472 // set up FSR0 with address from left
9473 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9474 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9478 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9480 pic16_aopOp (result,ic,FALSE);
9482 /* if bitfield then unpack the bits */
9483 if (IS_BITFIELD(retype))
9484 genUnpackBits (result, left, NULL, POINTER);
9486 /* we have can just get the values */
9487 int size = AOP_SIZE(result);
9490 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9493 /* fsr0 is loaded already -- VR */
9494 // pic16_loadFSR0( left );
9496 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9497 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9501 pic16_emitpcode(POC_MOVFF,
9502 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9503 pic16_popGet(AOP(result), offset++)));
9505 pic16_emitpcode(POC_MOVFF,
9506 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9507 pic16_popGet(AOP(result), offset++)));
9511 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9512 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9514 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9518 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9520 pic16_emitcode("mov","a,@%s",rname);
9521 pic16_aopPut(AOP(result),"a",offset);
9523 sprintf(buffer,"@%s",rname);
9524 pic16_aopPut(AOP(result),buffer,offset);
9528 pic16_emitcode("inc","%s",rname);
9533 /* now some housekeeping stuff */
9535 /* we had to allocate for this iCode */
9536 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9537 pic16_freeAsmop(NULL,aop,ic,TRUE);
9539 /* we did not allocate which means left
9540 already in a pointer register, then
9541 if size > 0 && this could be used again
9542 we have to point it back to where it
9544 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9545 if (AOP_SIZE(result) > 1 &&
9546 !OP_SYMBOL(left)->remat &&
9547 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9549 // int size = AOP_SIZE(result) - 1;
9551 // pic16_emitcode("dec","%s",rname);
9556 pic16_freeAsmop(left,NULL,ic,TRUE);
9557 pic16_freeAsmop(result,NULL,ic,TRUE);
9561 /*-----------------------------------------------------------------*/
9562 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
9563 /*-----------------------------------------------------------------*/
9564 static void genPagedPointerGet (operand *left,
9571 sym_link *rtype, *retype;
9573 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9575 rtype = operandType(result);
9576 retype= getSpec(rtype);
9578 pic16_aopOp(left,ic,FALSE);
9580 /* if the value is already in a pointer register
9581 then don't need anything more */
9582 if (!AOP_INPREG(AOP(left))) {
9583 /* otherwise get a free pointer register */
9585 preg = getFreePtr(ic,&aop,FALSE);
9586 pic16_emitcode("mov","%s,%s",
9588 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9589 rname = preg->name ;
9591 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9593 pic16_freeAsmop(left,NULL,ic,TRUE);
9594 pic16_aopOp (result,ic,FALSE);
9596 /* if bitfield then unpack the bits */
9597 if (IS_BITFIELD(retype))
9598 genUnpackBits (result,left,rname,PPOINTER);
9600 /* we have can just get the values */
9601 int size = AOP_SIZE(result);
9606 pic16_emitcode("movx","a,@%s",rname);
9607 pic16_aopPut(AOP(result),"a",offset);
9612 pic16_emitcode("inc","%s",rname);
9616 /* now some housekeeping stuff */
9618 /* we had to allocate for this iCode */
9619 pic16_freeAsmop(NULL,aop,ic,TRUE);
9621 /* we did not allocate which means left
9622 already in a pointer register, then
9623 if size > 0 && this could be used again
9624 we have to point it back to where it
9626 if (AOP_SIZE(result) > 1 &&
9627 !OP_SYMBOL(left)->remat &&
9628 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9630 int size = AOP_SIZE(result) - 1;
9632 pic16_emitcode("dec","%s",rname);
9637 pic16_freeAsmop(result,NULL,ic,TRUE);
9642 /*-----------------------------------------------------------------*/
9643 /* genFarPointerGet - gget value from far space */
9644 /*-----------------------------------------------------------------*/
9645 static void genFarPointerGet (operand *left,
9646 operand *result, iCode *ic)
9649 sym_link *retype = getSpec(operandType(result));
9651 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9653 pic16_aopOp(left,ic,FALSE);
9655 /* if the operand is already in dptr
9656 then we do nothing else we move the value to dptr */
9657 if (AOP_TYPE(left) != AOP_STR) {
9658 /* if this is remateriazable */
9659 if (AOP_TYPE(left) == AOP_IMMD)
9660 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9661 else { /* we need to get it byte by byte */
9662 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9663 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9664 if (options.model == MODEL_FLAT24)
9666 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9670 /* so dptr know contains the address */
9671 pic16_freeAsmop(left,NULL,ic,TRUE);
9672 pic16_aopOp(result,ic,FALSE);
9674 /* if bit then unpack */
9675 if (IS_BITFIELD(retype))
9676 genUnpackBits(result,left,"dptr",FPOINTER);
9678 size = AOP_SIZE(result);
9682 pic16_emitcode("movx","a,@dptr");
9683 pic16_aopPut(AOP(result),"a",offset++);
9685 pic16_emitcode("inc","dptr");
9689 pic16_freeAsmop(result,NULL,ic,TRUE);
9692 /*-----------------------------------------------------------------*/
9693 /* genCodePointerGet - get value from code space */
9694 /*-----------------------------------------------------------------*/
9695 static void genCodePointerGet (operand *left,
9696 operand *result, iCode *ic)
9699 sym_link *retype = getSpec(operandType(result));
9701 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9703 pic16_aopOp(left,ic,FALSE);
9705 /* if the operand is already in dptr
9706 then we do nothing else we move the value to dptr */
9707 if (AOP_TYPE(left) != AOP_STR) {
9708 /* if this is remateriazable */
9709 if (AOP_TYPE(left) == AOP_IMMD)
9710 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9711 else { /* we need to get it byte by byte */
9712 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9713 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9714 if (options.model == MODEL_FLAT24)
9716 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9720 /* so dptr know contains the address */
9721 pic16_freeAsmop(left,NULL,ic,TRUE);
9722 pic16_aopOp(result,ic,FALSE);
9724 /* if bit then unpack */
9725 if (IS_BITFIELD(retype))
9726 genUnpackBits(result,left,"dptr",CPOINTER);
9728 size = AOP_SIZE(result);
9732 pic16_emitcode("clr","a");
9733 pic16_emitcode("movc","a,@a+dptr");
9734 pic16_aopPut(AOP(result),"a",offset++);
9736 pic16_emitcode("inc","dptr");
9740 pic16_freeAsmop(result,NULL,ic,TRUE);
9743 /*-----------------------------------------------------------------*/
9744 /* genGenPointerGet - gget value from generic pointer space */
9745 /*-----------------------------------------------------------------*/
9746 static void genGenPointerGet (operand *left,
9747 operand *result, iCode *ic)
9749 int size, offset, lit;
9750 sym_link *retype = getSpec(operandType(result));
9752 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9753 pic16_aopOp(left,ic,FALSE);
9754 pic16_aopOp(result,ic,FALSE);
9755 size = AOP_SIZE(result);
9757 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9759 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9761 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9762 // load FSR0 from immediate
9763 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9765 // pic16_loadFSR0( left );
9770 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9772 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9779 else { /* we need to get it byte by byte */
9780 // set up FSR0 with address from left
9781 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9782 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9788 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9790 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9797 /* if bit then unpack */
9798 if (IS_BITFIELD(retype))
9799 genUnpackBits(result,left,"BAD",GPOINTER);
9802 pic16_freeAsmop(left,NULL,ic,TRUE);
9803 pic16_freeAsmop(result,NULL,ic,TRUE);
9807 /*-----------------------------------------------------------------*/
9808 /* genConstPointerGet - get value from const generic pointer space */
9809 /*-----------------------------------------------------------------*/
9810 static void genConstPointerGet (operand *left,
9811 operand *result, iCode *ic)
9813 //sym_link *retype = getSpec(operandType(result));
9814 // symbol *albl = newiTempLabel(NULL); // patch 15
9815 // symbol *blbl = newiTempLabel(NULL); //
9816 // PIC_OPCODE poc; // patch 15
9820 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9821 pic16_aopOp(left,ic,FALSE);
9822 pic16_aopOp(result,ic,TRUE);
9823 size = AOP_SIZE(result);
9825 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9827 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9829 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9830 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9831 pic16_emitpLabel(albl->key);
9833 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9835 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9836 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9837 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9838 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9839 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9841 pic16_emitpLabel(blbl->key);
9843 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9847 // set up table pointer
9848 if( (AOP_TYPE(left) == AOP_PCODE)
9849 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9850 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
9852 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9853 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9854 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9855 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9856 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9857 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9861 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9862 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9863 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9869 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9870 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9874 pic16_freeAsmop(left,NULL,ic,TRUE);
9875 pic16_freeAsmop(result,NULL,ic,TRUE);
9880 /*-----------------------------------------------------------------*/
9881 /* genPointerGet - generate code for pointer get */
9882 /*-----------------------------------------------------------------*/
9883 static void genPointerGet (iCode *ic)
9885 operand *left, *result ;
9886 sym_link *type, *etype;
9889 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9892 result = IC_RESULT(ic) ;
9894 /* depending on the type of pointer we need to
9895 move it to the correct pointer register */
9896 type = operandType(left);
9897 etype = getSpec(type);
9900 if (IS_PTR_CONST(type))
9902 if (IS_CODEPTR(type))
9904 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9906 /* if left is of type of pointer then it is simple */
9907 if (IS_PTR(type) && !IS_FUNC(type->next))
9908 p_type = DCL_TYPE(type);
9910 /* we have to go by the storage class */
9911 p_type = PTR_TYPE(SPEC_OCLS(etype));
9913 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9915 if (SPEC_OCLS(etype)->codesp ) {
9916 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9917 //p_type = CPOINTER ;
9920 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9921 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9922 /*p_type = FPOINTER ;*/
9924 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9925 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9926 /* p_type = PPOINTER; */
9928 if (SPEC_OCLS(etype) == idata )
9929 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9930 /* p_type = IPOINTER; */
9932 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9933 /* p_type = POINTER ; */
9936 /* now that we have the pointer type we assign
9937 the pointer values */
9942 genNearPointerGet (left,result,ic);
9946 genPagedPointerGet(left,result,ic);
9950 genFarPointerGet (left,result,ic);
9954 genConstPointerGet (left,result,ic);
9955 //pic16_emitcodePointerGet (left,result,ic);
9960 if (IS_PTR_CONST(type))
9961 genConstPointerGet (left,result,ic);
9964 genGenPointerGet (left,result,ic);
9968 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9969 "genPointerGet: illegal pointer type");
9975 /*-----------------------------------------------------------------*/
9976 /* genPackBits - generates code for packed bit storage */
9977 /*-----------------------------------------------------------------*/
9978 static void genPackBits (sym_link *etype , operand *result,
9980 char *rname, int p_type)
9988 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9989 blen = SPEC_BLEN(etype);
9990 bstr = SPEC_BSTR(etype);
9992 if(AOP_TYPE(right) == AOP_LIT) {
9993 if((blen == 1) && (bstr < 8)) {
9995 /* it is a single bit, so use the appropriate bit instructions */
9997 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9999 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10000 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10001 if((p_type == POINTER) && (result)) {
10002 /* workaround to reduce the extra lfsr instruction */
10004 pic16_emitpcode(POC_BSF,
10005 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10007 pic16_emitpcode(POC_BCF,
10008 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
10013 pic16_emitpcode(POC_BSF,
10014 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10016 pic16_emitpcode(POC_BCF,
10017 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10024 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
10027 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
10029 /* if the bit lenth is less than or */
10030 /* it exactly fits a byte then */
10031 if((shCnt=SPEC_BSTR(etype))
10032 || SPEC_BLEN(etype) <= 8 ) {
10034 /* shift left acc */
10037 /* using PRODL as a temporary register here */
10038 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
10044 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10045 // pic16_emitcode ("mov","b,a");
10046 // pic16_emitcode("mov","a,@%s",rname);
10050 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10051 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
10052 (unsigned char)(0xff >> (8-bstr))) ));
10053 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
10054 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10061 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10062 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10067 if ( SPEC_BLEN(etype) <= 8 )
10070 pic16_emitcode("inc","%s",rname);
10071 rLen = SPEC_BLEN(etype) ;
10075 /* now generate for lengths greater than one byte */
10078 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
10088 pic16_emitcode("mov","@%s,a",rname);
10090 pic16_emitcode("mov","@%s,%s",rname,l);
10095 pic16_emitcode("movx","@dptr,a");
10100 DEBUGpic16_emitcode(";lcall","__gptrput");
10103 pic16_emitcode ("inc","%s",rname);
10108 /* last last was not complete */
10110 /* save the byte & read byte */
10113 pic16_emitcode ("mov","b,a");
10114 pic16_emitcode("mov","a,@%s",rname);
10118 pic16_emitcode ("mov","b,a");
10119 pic16_emitcode("movx","a,@dptr");
10123 pic16_emitcode ("push","b");
10124 pic16_emitcode ("push","acc");
10125 pic16_emitcode ("lcall","__gptrget");
10126 pic16_emitcode ("pop","b");
10130 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
10131 pic16_emitcode ("orl","a,b");
10134 if (p_type == GPOINTER)
10135 pic16_emitcode("pop","b");
10140 pic16_emitcode("mov","@%s,a",rname);
10144 pic16_emitcode("movx","@dptr,a");
10148 DEBUGpic16_emitcode(";lcall","__gptrput");
10152 /*-----------------------------------------------------------------*/
10153 /* genDataPointerSet - remat pointer to data space */
10154 /*-----------------------------------------------------------------*/
10155 static void genDataPointerSet(operand *right,
10159 int size, offset = 0, resoffset=0 ;
10161 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10162 pic16_aopOp(right,ic,FALSE);
10164 size = AOP_SIZE(right);
10166 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10169 if ( AOP_TYPE(result) == AOP_PCODE) {
10170 fprintf(stderr,"genDataPointerSet %s, %d\n",
10171 AOP(result)->aopu.pcop->name,
10172 (AOP(result)->aopu.pcop->type == PO_DIR)?
10173 PCOR(AOP(result)->aopu.pcop)->instance:
10174 PCOI(AOP(result)->aopu.pcop)->offset);
10178 if(AOP(result)->aopu.pcop->type == PO_DIR)
10179 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
10182 if (AOP_TYPE(right) == AOP_LIT) {
10183 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
10185 lit = lit >> (8*offset);
10187 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
10188 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
10190 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
10193 mov2w(AOP(right), offset);
10194 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
10200 pic16_freeAsmop(right,NULL,ic,TRUE);
10205 /*-----------------------------------------------------------------*/
10206 /* genNearPointerSet - pic16_emitcode for near pointer put */
10207 /*-----------------------------------------------------------------*/
10208 static void genNearPointerSet (operand *right,
10215 sym_link *ptype = operandType(result);
10216 sym_link *resetype;
10218 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10219 retype= getSpec(operandType(right));
10220 resetype = getSpec(operandType(result));
10222 pic16_aopOp(result,ic,FALSE);
10224 /* if the result is rematerializable &
10225 * in data space & not a bit variable */
10227 /* and result is not a bit variable */
10228 if (AOP_TYPE(result) == AOP_PCODE
10229 // && AOP_TYPE(result) == AOP_IMMD
10230 && DCL_TYPE(ptype) == POINTER
10231 && !IS_BITFIELD(retype)
10232 && !IS_BITFIELD(resetype)) {
10234 genDataPointerSet (right,result,ic);
10235 pic16_freeAsmop(result,NULL,ic,TRUE);
10239 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10240 pic16_aopOp(right,ic,FALSE);
10241 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10243 /* if the value is already in a pointer register
10244 * then don't need anything more */
10245 if (!AOP_INPREG(AOP(result))) {
10246 /* otherwise get a free pointer register */
10247 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10249 if( (AOP_TYPE(result) == AOP_PCODE)
10250 && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10251 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10253 if(!IS_BITFIELD(resetype))
10254 pic16_loadFSR0( result ); // patch 10
10256 // set up FSR0 with address of result
10257 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10258 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10263 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10265 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10267 /* if bitfield then unpack the bits */
10268 if (IS_BITFIELD(resetype)) {
10269 genPackBits (resetype, result, right, NULL, POINTER);
10271 /* we have can just get the values */
10272 int size = AOP_SIZE(right);
10275 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10277 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10280 //pic16_emitcode("mov","@%s,a",rname);
10281 pic16_emitcode("movf","indf0,w ;1");
10284 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
10285 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
10287 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
10289 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
10291 } else { // no literal //
10293 pic16_emitpcode(POC_MOVFF, //
10294 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10295 pic16_popCopyReg(&pic16_pc_postinc0))); //
10297 pic16_emitpcode(POC_MOVFF, //
10298 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10299 pic16_popCopyReg(&pic16_pc_indf0))); //
10307 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10308 /* now some housekeeping stuff */
10310 /* we had to allocate for this iCode */
10311 pic16_freeAsmop(NULL,aop,ic,TRUE);
10313 /* we did not allocate which means left
10314 * already in a pointer register, then
10315 * if size > 0 && this could be used again
10316 * we have to point it back to where it
10318 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10319 if (AOP_SIZE(right) > 1
10320 && !OP_SYMBOL(result)->remat
10321 && ( OP_SYMBOL(result)->liveTo > ic->seq
10324 int size = AOP_SIZE(right) - 1;
10327 pic16_emitcode("decf","fsr0,f");
10328 //pic16_emitcode("dec","%s",rname);
10332 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10335 pic16_freeAsmop(right,NULL,ic,TRUE);
10336 pic16_freeAsmop(result,NULL,ic,TRUE);
10339 /*-----------------------------------------------------------------*/
10340 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
10341 /*-----------------------------------------------------------------*/
10342 static void genPagedPointerSet (operand *right,
10347 regs *preg = NULL ;
10351 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10353 retype= getSpec(operandType(right));
10355 pic16_aopOp(result,ic,FALSE);
10357 /* if the value is already in a pointer register
10358 then don't need anything more */
10359 if (!AOP_INPREG(AOP(result))) {
10360 /* otherwise get a free pointer register */
10362 preg = getFreePtr(ic,&aop,FALSE);
10363 pic16_emitcode("mov","%s,%s",
10365 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10366 rname = preg->name ;
10368 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10370 pic16_freeAsmop(result,NULL,ic,TRUE);
10371 pic16_aopOp (right,ic,FALSE);
10373 /* if bitfield then unpack the bits */
10374 if (IS_BITFIELD(retype))
10375 genPackBits (retype,result,right,rname,PPOINTER);
10377 /* we have can just get the values */
10378 int size = AOP_SIZE(right);
10382 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10385 pic16_emitcode("movx","@%s,a",rname);
10388 pic16_emitcode("inc","%s",rname);
10394 /* now some housekeeping stuff */
10396 /* we had to allocate for this iCode */
10397 pic16_freeAsmop(NULL,aop,ic,TRUE);
10399 /* we did not allocate which means left
10400 already in a pointer register, then
10401 if size > 0 && this could be used again
10402 we have to point it back to where it
10404 if (AOP_SIZE(right) > 1 &&
10405 !OP_SYMBOL(result)->remat &&
10406 ( OP_SYMBOL(result)->liveTo > ic->seq ||
10408 int size = AOP_SIZE(right) - 1;
10410 pic16_emitcode("dec","%s",rname);
10415 pic16_freeAsmop(right,NULL,ic,TRUE);
10420 /*-----------------------------------------------------------------*/
10421 /* genFarPointerSet - set value from far space */
10422 /*-----------------------------------------------------------------*/
10423 static void genFarPointerSet (operand *right,
10424 operand *result, iCode *ic)
10427 sym_link *retype = getSpec(operandType(right));
10429 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10430 pic16_aopOp(result,ic,FALSE);
10432 /* if the operand is already in dptr
10433 then we do nothing else we move the value to dptr */
10434 if (AOP_TYPE(result) != AOP_STR) {
10435 /* if this is remateriazable */
10436 if (AOP_TYPE(result) == AOP_IMMD)
10437 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10438 else { /* we need to get it byte by byte */
10439 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10440 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10441 if (options.model == MODEL_FLAT24)
10443 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10447 /* so dptr know contains the address */
10448 pic16_freeAsmop(result,NULL,ic,TRUE);
10449 pic16_aopOp(right,ic,FALSE);
10451 /* if bit then unpack */
10452 if (IS_BITFIELD(retype))
10453 genPackBits(retype,result,right,"dptr",FPOINTER);
10455 size = AOP_SIZE(right);
10459 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10461 pic16_emitcode("movx","@dptr,a");
10463 pic16_emitcode("inc","dptr");
10467 pic16_freeAsmop(right,NULL,ic,TRUE);
10470 /*-----------------------------------------------------------------*/
10471 /* genGenPointerSet - set value from generic pointer space */
10472 /*-----------------------------------------------------------------*/
10473 static void genGenPointerSet (operand *right,
10474 operand *result, iCode *ic)
10476 int i, size, offset, lit;
10477 sym_link *retype = getSpec(operandType(right));
10479 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10481 pic16_aopOp(result,ic,FALSE);
10482 pic16_aopOp(right,ic,FALSE);
10483 size = AOP_SIZE(right);
10486 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10488 /* if the operand is already in dptr
10489 then we do nothing else we move the value to dptr */
10490 if (AOP_TYPE(result) != AOP_STR) {
10491 /* if this is remateriazable */
10492 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10493 // WARNING: anythig until "else" is untested!
10494 if (AOP_TYPE(result) == AOP_IMMD) {
10495 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10496 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10497 // load FSR0 from immediate
10498 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10502 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10504 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10510 else { /* we need to get it byte by byte */
10511 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10512 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10514 // set up FSR0 with address of result
10515 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10516 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10518 /* hack hack! see if this the FSR. If so don't load W */
10519 if(AOP_TYPE(right) != AOP_ACC) {
10521 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10523 if(AOP_TYPE(right) == AOP_LIT)
10526 // note: pic16_popGet handles sign extension
10527 for(i=0;i<size;i++) {
10528 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10530 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10532 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10537 for(i=0;i<size;i++) {
10539 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10540 pic16_popCopyReg(&pic16_pc_postinc0)));
10542 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10543 pic16_popCopyReg(&pic16_pc_indf0)));
10549 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10550 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10552 } // if (AOP_TYPE(result) != AOP_IMMD)
10554 } // if (AOP_TYPE(result) != AOP_STR)
10555 /* so dptr know contains the address */
10558 /* if bit then unpack */
10559 if (IS_BITFIELD(retype))
10560 genPackBits(retype,result,right,"dptr",GPOINTER);
10562 size = AOP_SIZE(right);
10565 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
10567 // set up FSR0 with address of result
10568 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10569 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10572 if (AOP_TYPE(right) == AOP_LIT) {
10573 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10575 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10577 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10579 } else { // no literal
10581 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10583 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10591 pic16_freeAsmop(right,NULL,ic,TRUE);
10592 pic16_freeAsmop(result,NULL,ic,TRUE);
10595 /*-----------------------------------------------------------------*/
10596 /* genPointerSet - stores the value into a pointer location */
10597 /*-----------------------------------------------------------------*/
10598 static void genPointerSet (iCode *ic)
10600 operand *right, *result ;
10601 sym_link *type, *etype;
10604 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10606 right = IC_RIGHT(ic);
10607 result = IC_RESULT(ic) ;
10609 /* depending on the type of pointer we need to
10610 move it to the correct pointer register */
10611 type = operandType(result);
10612 etype = getSpec(type);
10613 /* if left is of type of pointer then it is simple */
10614 if (IS_PTR(type) && !IS_FUNC(type->next)) {
10615 p_type = DCL_TYPE(type);
10618 /* we have to go by the storage class */
10619 p_type = PTR_TYPE(SPEC_OCLS(etype));
10621 /* if (SPEC_OCLS(etype)->codesp ) { */
10622 /* p_type = CPOINTER ; */
10625 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10626 /* p_type = FPOINTER ; */
10628 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10629 /* p_type = PPOINTER ; */
10631 /* if (SPEC_OCLS(etype) == idata ) */
10632 /* p_type = IPOINTER ; */
10634 /* p_type = POINTER ; */
10637 /* now that we have the pointer type we assign
10638 the pointer values */
10643 genNearPointerSet (right,result,ic);
10647 genPagedPointerSet (right,result,ic);
10651 genFarPointerSet (right,result,ic);
10655 genGenPointerSet (right,result,ic);
10659 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10660 "genPointerSet: illegal pointer type");
10664 /*-----------------------------------------------------------------*/
10665 /* genIfx - generate code for Ifx statement */
10666 /*-----------------------------------------------------------------*/
10667 static void genIfx (iCode *ic, iCode *popIc)
10669 operand *cond = IC_COND(ic);
10672 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10674 pic16_aopOp(cond,ic,FALSE);
10676 /* get the value into acc */
10677 if (AOP_TYPE(cond) != AOP_CRY)
10678 pic16_toBoolean(cond);
10681 /* the result is now in the accumulator */
10682 pic16_freeAsmop(cond,NULL,ic,TRUE);
10684 /* if there was something to be popped then do it */
10688 /* if the condition is a bit variable */
10689 if (isbit && IS_ITEMP(cond) &&
10691 genIfxJump(ic,SPIL_LOC(cond)->rname);
10692 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10695 if (isbit && !IS_ITEMP(cond))
10696 genIfxJump(ic,OP_SYMBOL(cond)->rname);
10698 genIfxJump(ic,"a");
10704 /*-----------------------------------------------------------------*/
10705 /* genAddrOf - generates code for address of */
10706 /*-----------------------------------------------------------------*/
10707 static void genAddrOf (iCode *ic)
10709 operand *result, *left;
10711 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
10712 pCodeOp *pcop0, *pcop1, *pcop2;
10714 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10716 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10717 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10719 sym = OP_SYMBOL( left );
10721 size = AOP_SIZE(IC_RESULT(ic));
10725 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
10730 // if(pic16_debug_verbose) {
10731 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10732 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10735 /* Assume that what we want the address of is in data space
10736 * since there is no stack on the PIC, yet! -- VR */
10738 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10741 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10744 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10748 pic16_emitpcode(POC_MOVLW, pcop0);
10749 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10750 pic16_emitpcode(POC_MOVLW, pcop1);
10751 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10752 pic16_emitpcode(POC_MOVLW, pcop2);
10753 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10756 pic16_emitpcode(POC_MOVLW, pcop0);
10757 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10758 pic16_emitpcode(POC_MOVLW, pcop1);
10759 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10761 pic16_emitpcode(POC_MOVLW, pcop0);
10762 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10765 pic16_freeAsmop(result,NULL,ic,TRUE);
10766 pic16_freeAsmop(left, NULL, ic, FALSE);
10771 /*-----------------------------------------------------------------*/
10772 /* genFarFarAssign - assignment when both are in far space */
10773 /*-----------------------------------------------------------------*/
10774 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10776 int size = AOP_SIZE(right);
10779 /* first push the right side on to the stack */
10781 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10783 pic16_emitcode ("push","acc");
10786 pic16_freeAsmop(right,NULL,ic,FALSE);
10787 /* now assign DPTR to result */
10788 pic16_aopOp(result,ic,FALSE);
10789 size = AOP_SIZE(result);
10791 pic16_emitcode ("pop","acc");
10792 pic16_aopPut(AOP(result),"a",--offset);
10794 pic16_freeAsmop(result,NULL,ic,FALSE);
10799 /*-----------------------------------------------------------------*/
10800 /* genAssign - generate code for assignment */
10801 /*-----------------------------------------------------------------*/
10802 static void genAssign (iCode *ic)
10804 operand *result, *right;
10805 int size, offset,know_W;
10806 unsigned long lit = 0L;
10808 result = IC_RESULT(ic);
10809 right = IC_RIGHT(ic) ;
10811 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10813 /* if they are the same */
10814 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10817 pic16_aopOp(right,ic,FALSE);
10818 pic16_aopOp(result,ic,TRUE);
10820 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10822 /* if they are the same registers */
10823 if (pic16_sameRegs(AOP(right),AOP(result)))
10826 /* if the result is a bit */
10827 if (AOP_TYPE(result) == AOP_CRY) {
10828 /* if the right size is a literal then
10829 we know what the value is */
10830 if (AOP_TYPE(right) == AOP_LIT) {
10832 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10833 pic16_popGet(AOP(result),0));
10835 if (((int) operandLitValue(right)))
10836 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10837 AOP(result)->aopu.aop_dir,
10838 AOP(result)->aopu.aop_dir);
10840 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10841 AOP(result)->aopu.aop_dir,
10842 AOP(result)->aopu.aop_dir);
10846 /* the right is also a bit variable */
10847 if (AOP_TYPE(right) == AOP_CRY) {
10848 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10849 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10850 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10852 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10853 AOP(result)->aopu.aop_dir,
10854 AOP(result)->aopu.aop_dir);
10855 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10856 AOP(right)->aopu.aop_dir,
10857 AOP(right)->aopu.aop_dir);
10858 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10859 AOP(result)->aopu.aop_dir,
10860 AOP(result)->aopu.aop_dir);
10864 /* we need to or */
10865 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10866 pic16_toBoolean(right);
10868 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10869 //pic16_aopPut(AOP(result),"a",0);
10873 /* bit variables done */
10875 size = AOP_SIZE(result);
10878 if(AOP_TYPE(right) == AOP_LIT) {
10879 if(!IS_FLOAT(operandType( right )))
10880 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10883 unsigned long lit_int;
10887 /* take care if literal is a float */
10888 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10889 lit = info.lit_int;
10893 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10894 // sizeof(unsigned long int), sizeof(float));
10896 if(AOP_TYPE(right) != AOP_LIT
10897 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10898 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10899 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
10901 // set up table pointer
10902 if( (AOP_TYPE(right) == AOP_PCODE)
10903 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10904 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10906 fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
10907 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10908 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10909 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10910 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10911 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10912 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10914 fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
10915 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10916 pic16_popCopyReg(&pic16_pc_tblptrl)));
10917 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10918 pic16_popCopyReg(&pic16_pc_tblptrh)));
10919 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10920 pic16_popCopyReg(&pic16_pc_tblptru)));
10923 size = min(AOP_SIZE(right), AOP_SIZE(result));
10925 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10926 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10927 pic16_popGet(AOP(result),offset)));
10931 if(AOP_SIZE(result) > AOP_SIZE(right)) {
10932 size = AOP_SIZE(result) - AOP_SIZE(right);
10934 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10944 /* VR - What is this?! */
10945 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10946 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10947 if(aopIdx(AOP(result),0) == 4) {
10949 /* this is a workaround to save value of right into wreg too,
10950 * value of wreg is going to be used later */
10951 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10952 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10953 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10957 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10963 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10964 if(AOP_TYPE(right) == AOP_LIT) {
10966 if(know_W != (lit&0xff))
10967 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10969 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10971 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10975 } else if (AOP_TYPE(right) == AOP_CRY) {
10976 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10978 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10979 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10981 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10982 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10983 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10985 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10988 /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10989 normally should work, but mind that the W register live range
10990 is not checked, so if the code generator assumes that the W
10991 is already loaded after such a pair, wrong code will be generated.
10993 Checking the live range is the next step.
10994 This is experimental code yet and has not been fully tested yet.
10995 USE WITH CARE. Revert to old code by setting 0 to the condition above.
10996 Vangelis Rokas 030603 (vrokas@otenet.gr) */
10998 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11000 /* This is the old code, which is assumed(?!) that works fine(!?) */
11002 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11003 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11012 pic16_freeAsmop (right,NULL,ic,FALSE);
11013 pic16_freeAsmop (result,NULL,ic,TRUE);
11016 /*-----------------------------------------------------------------*/
11017 /* genJumpTab - generates code for jump table */
11018 /*-----------------------------------------------------------------*/
11019 static void genJumpTab (iCode *ic)
11024 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11026 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
11027 /* get the condition into accumulator */
11028 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
11030 /* multiply by three */
11031 pic16_emitcode("add","a,acc");
11032 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
11034 jtab = newiTempLabel(NULL);
11035 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
11036 pic16_emitcode("jmp","@a+dptr");
11037 pic16_emitcode("","%05d_DS_:",jtab->key+100);
11039 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
11040 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
11042 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
11043 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
11044 pic16_emitpLabel(jtab->key);
11046 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
11048 /* now generate the jump labels */
11049 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
11050 jtab = setNextItem(IC_JTLABELS(ic))) {
11051 pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
11052 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
11058 /*-----------------------------------------------------------------*/
11059 /* genMixedOperation - gen code for operators between mixed types */
11060 /*-----------------------------------------------------------------*/
11062 TSD - Written for the PIC port - but this unfortunately is buggy.
11063 This routine is good in that it is able to efficiently promote
11064 types to different (larger) sizes. Unfortunately, the temporary
11065 variables that are optimized out by this routine are sometimes
11066 used in other places. So until I know how to really parse the
11067 iCode tree, I'm going to not be using this routine :(.
11069 static int genMixedOperation (iCode *ic)
11072 operand *result = IC_RESULT(ic);
11073 sym_link *ctype = operandType(IC_LEFT(ic));
11074 operand *right = IC_RIGHT(ic);
11080 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
11082 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11088 nextright = IC_RIGHT(nextic);
11089 nextleft = IC_LEFT(nextic);
11090 nextresult = IC_RESULT(nextic);
11092 pic16_aopOp(right,ic,FALSE);
11093 pic16_aopOp(result,ic,FALSE);
11094 pic16_aopOp(nextright, nextic, FALSE);
11095 pic16_aopOp(nextleft, nextic, FALSE);
11096 pic16_aopOp(nextresult, nextic, FALSE);
11098 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
11100 operand *t = right;
11104 pic16_emitcode(";remove right +","");
11106 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
11108 operand *t = right;
11112 pic16_emitcode(";remove left +","");
11116 big = AOP_SIZE(nextleft);
11117 small = AOP_SIZE(nextright);
11119 switch(nextic->op) {
11122 pic16_emitcode(";optimize a +","");
11123 /* if unsigned or not an integral type */
11124 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
11125 pic16_emitcode(";add a bit to something","");
11128 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
11130 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
11131 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
11132 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
11134 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
11142 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11143 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11144 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11147 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11149 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11150 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
11151 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
11152 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11153 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
11156 pic16_emitcode("rlf","known_zero,w");
11163 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11164 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11165 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11167 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11177 pic16_freeAsmop(right,NULL,ic,TRUE);
11178 pic16_freeAsmop(result,NULL,ic,TRUE);
11179 pic16_freeAsmop(nextright,NULL,ic,TRUE);
11180 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
11182 nextic->generated = 1;
11189 /*-----------------------------------------------------------------*/
11190 /* genCast - gen code for casting */
11191 /*-----------------------------------------------------------------*/
11192 static void genCast (iCode *ic)
11194 operand *result = IC_RESULT(ic);
11195 sym_link *ctype = operandType(IC_LEFT(ic));
11196 sym_link *rtype = operandType(IC_RIGHT(ic));
11197 operand *right = IC_RIGHT(ic);
11200 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11201 /* if they are equivalent then do nothing */
11202 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
11205 pic16_aopOp(right,ic,FALSE) ;
11206 pic16_aopOp(result,ic,FALSE);
11208 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11210 /* if the result is a bit */
11211 if (AOP_TYPE(result) == AOP_CRY) {
11213 /* if the right size is a literal then
11214 * we know what the value is */
11215 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11217 if (AOP_TYPE(right) == AOP_LIT) {
11218 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11219 pic16_popGet(AOP(result),0));
11221 if (((int) operandLitValue(right)))
11222 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
11223 AOP(result)->aopu.aop_dir,
11224 AOP(result)->aopu.aop_dir);
11226 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
11227 AOP(result)->aopu.aop_dir,
11228 AOP(result)->aopu.aop_dir);
11232 /* the right is also a bit variable */
11233 if (AOP_TYPE(right) == AOP_CRY) {
11235 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11237 pic16_emitcode("clrc","");
11238 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11239 AOP(right)->aopu.aop_dir,
11240 AOP(right)->aopu.aop_dir);
11241 pic16_aopPut(AOP(result),"c",0);
11245 /* we need to or */
11246 if (AOP_TYPE(right) == AOP_REG) {
11247 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
11248 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
11249 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
11251 pic16_toBoolean(right);
11252 pic16_aopPut(AOP(result),"a",0);
11256 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11259 size = AOP_SIZE(result);
11261 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11263 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
11264 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11265 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
11268 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11273 /* if they are the same size : or less */
11274 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11276 /* if they are in the same place */
11277 if (pic16_sameRegs(AOP(right),AOP(result)))
11280 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11282 if (IS_PTR_CONST(rtype))
11284 if (IS_CODEPTR(rtype))
11286 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11289 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11291 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11293 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11296 if(AOP_TYPE(right) == AOP_IMMD) {
11297 pCodeOp *pcop0, *pcop1, *pcop2;
11298 symbol *sym = OP_SYMBOL( right );
11300 size = AOP_SIZE(result);
11302 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11304 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11306 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11309 pic16_emitpcode(POC_MOVLW, pcop0);
11310 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11311 pic16_emitpcode(POC_MOVLW, pcop1);
11312 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11313 pic16_emitpcode(POC_MOVLW, pcop2);
11314 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11317 pic16_emitpcode(POC_MOVLW, pcop0);
11318 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11319 pic16_emitpcode(POC_MOVLW, pcop1);
11320 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11322 pic16_emitpcode(POC_MOVLW, pcop0);
11323 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11327 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11328 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11329 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11330 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11331 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11332 if(AOP_SIZE(result) <2)
11333 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11335 /* if they in different places then copy */
11336 size = AOP_SIZE(result);
11339 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11340 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11347 /* if the result is of type pointer */
11348 if (IS_PTR(ctype)) {
11350 sym_link *type = operandType(right);
11351 sym_link *etype = getSpec(type);
11353 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
11355 /* pointer to generic pointer */
11356 if (IS_GENPTR(ctype)) {
11360 p_type = DCL_TYPE(type);
11362 /* we have to go by the storage class */
11363 p_type = PTR_TYPE(SPEC_OCLS(etype));
11365 /* if (SPEC_OCLS(etype)->codesp ) */
11366 /* p_type = CPOINTER ; */
11368 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11369 /* p_type = FPOINTER ; */
11371 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11372 /* p_type = PPOINTER; */
11374 /* if (SPEC_OCLS(etype) == idata ) */
11375 /* p_type = IPOINTER ; */
11377 /* p_type = POINTER ; */
11380 /* the first two bytes are known */
11381 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
11382 size = GPTRSIZE - 1;
11385 if(offset < AOP_SIZE(right)) {
11386 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
11387 if ((AOP_TYPE(right) == AOP_PCODE) &&
11388 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11389 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11390 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11392 pic16_aopPut(AOP(result),
11393 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11397 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11400 /* the last byte depending on type */
11404 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11407 pic16_emitcode(";BUG!? ","%d",__LINE__);
11411 pic16_emitcode(";BUG!? ","%d",__LINE__);
11415 pic16_emitcode(";BUG!? ","%d",__LINE__);
11420 /* this should never happen */
11421 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11422 "got unknown pointer type");
11425 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
11429 /* just copy the pointers */
11430 size = AOP_SIZE(result);
11433 pic16_aopPut(AOP(result),
11434 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11443 /* so we now know that the size of destination is greater
11444 than the size of the source.
11445 Now, if the next iCode is an operator then we might be
11446 able to optimize the operation without performing a cast.
11448 if(genMixedOperation(ic))
11451 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11453 /* we move to result for the size of source */
11454 size = AOP_SIZE(right);
11457 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11458 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11459 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11463 /* now depending on the sign of the destination */
11464 size = AOP_SIZE(result) - AOP_SIZE(right);
11465 /* if unsigned or not an integral type */
11466 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11468 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11470 /* we need to extend the sign :( */
11473 /* Save one instruction of casting char to int */
11474 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11475 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11476 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
11478 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11481 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11483 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11485 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
11488 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
11493 pic16_freeAsmop(right,NULL,ic,TRUE);
11494 pic16_freeAsmop(result,NULL,ic,TRUE);
11498 /*-----------------------------------------------------------------*/
11499 /* genDjnz - generate decrement & jump if not zero instrucion */
11500 /*-----------------------------------------------------------------*/
11501 static int genDjnz (iCode *ic, iCode *ifx)
11503 symbol *lbl, *lbl1;
11504 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11509 /* if the if condition has a false label
11510 then we cannot save */
11514 /* if the minus is not of the form
11516 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11517 !IS_OP_LITERAL(IC_RIGHT(ic)))
11520 if (operandLitValue(IC_RIGHT(ic)) != 1)
11523 /* if the size of this greater than one then no
11525 if (getSize(operandType(IC_RESULT(ic))) > 1)
11528 /* otherwise we can save BIG */
11529 lbl = newiTempLabel(NULL);
11530 lbl1= newiTempLabel(NULL);
11532 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11534 if (IS_AOP_PREG(IC_RESULT(ic))) {
11535 pic16_emitcode("dec","%s",
11536 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11537 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11538 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11542 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11543 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11545 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11546 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
11549 /* pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11550 /* pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11551 /* pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11552 /* pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11555 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11556 ifx->generated = 1;
11560 /*-----------------------------------------------------------------*/
11561 /* genReceive - generate code for a receive iCode */
11562 /*-----------------------------------------------------------------*/
11563 static void genReceive (iCode *ic)
11565 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11568 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11569 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
11571 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11573 if (isOperandInFarSpace(IC_RESULT(ic)) &&
11574 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11575 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11577 int size = getSize(operandType(IC_RESULT(ic)));
11578 int offset = pic16_fReturnSizePic - size;
11582 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11583 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11587 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
11589 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11590 size = AOP_SIZE(IC_RESULT(ic));
11593 pic16_emitcode ("pop","acc");
11594 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11597 DEBUGpic16_emitcode ("; ***","2 %s %d",__FUNCTION__,__LINE__);
11600 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11602 assignResultValue(IC_RESULT(ic), 0);
11605 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11608 /*-----------------------------------------------------------------*/
11609 /* genDummyRead - generate code for dummy read of volatiles */
11610 /*-----------------------------------------------------------------*/
11612 genDummyRead (iCode * ic)
11614 pic16_emitcode ("; genDummyRead","");
11615 pic16_emitcode ("; not implemented","");
11620 /*-----------------------------------------------------------------*/
11621 /* genpic16Code - generate code for pic16 based controllers */
11622 /*-----------------------------------------------------------------*/
11624 * At this point, ralloc.c has gone through the iCode and attempted
11625 * to optimize in a way suitable for a PIC. Now we've got to generate
11626 * PIC instructions that correspond to the iCode.
11628 * Once the instructions are generated, we'll pass through both the
11629 * peep hole optimizer and the pCode optimizer.
11630 *-----------------------------------------------------------------*/
11632 void genpic16Code (iCode *lic)
11637 lineHead = lineCurr = NULL;
11639 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11640 pic16_addpBlock(pb);
11643 /* if debug information required */
11644 if (options.debug && currFunc) {
11646 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11651 for (ic = lic ; ic ; ic = ic->next ) {
11653 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11654 if ( cln != ic->lineno ) {
11655 if ( options.debug ) {
11656 debugFile->writeCLine (ic);
11659 if(!options.noCcodeInAsm) {
11660 pic16_addpCode2pBlock(pb,
11661 pic16_newpCodeCSource(ic->lineno, ic->filename,
11662 printCLine(ic->filename, ic->lineno)));
11668 if(options.iCodeInAsm) {
11670 /* insert here code to print iCode as comment */
11671 l = Safe_strdup(printILine(ic));
11672 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11675 /* if the result is marked as
11676 spilt and rematerializable or code for
11677 this has already been generated then
11679 if (resultRemat(ic) || ic->generated )
11682 /* depending on the operation */
11701 /* IPOP happens only when trying to restore a
11702 spilt live range, if there is an ifx statement
11703 following this pop then the if statement might
11704 be using some of the registers being popped which
11705 would destroy the contents of the register so
11706 we need to check for this condition and handle it */
11708 ic->next->op == IFX &&
11709 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
11710 genIfx (ic->next,ic);
11728 genEndFunction (ic);
11744 pic16_genPlus (ic) ;
11748 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11749 pic16_genMinus (ic);
11765 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
11769 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11776 /* note these two are xlated by algebraic equivalence
11777 during parsing SDCC.y */
11778 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11779 "got '>=' or '<=' shouldn't have come here");
11783 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11795 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11799 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11803 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11827 genRightShift (ic);
11830 case GET_VALUE_AT_ADDRESS:
11835 if (POINTER_SET(ic))
11862 addSet(&_G.sendSet,ic);
11865 case DUMMY_READ_VOLATILE:
11875 /* now we are ready to call the
11876 peep hole optimizer */
11877 if (!options.nopeep) {
11878 peepHole (&lineHead);
11880 /* now do the actual printing */
11881 printLine (lineHead,codeOutFile);
11884 DFPRINTF((stderr,"printing pBlock\n\n"));
11885 pic16_printpBlock(stdout,pb);