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)) ))
876 static int aopIdx (asmop *aop, int offset)
881 if(aop->type != AOP_REG)
884 return aop->aopu.aop_reg[offset]->rIdx;
887 /*-----------------------------------------------------------------*/
888 /* regsInCommon - two operands have some registers in common */
889 /*-----------------------------------------------------------------*/
890 static bool regsInCommon (operand *op1, operand *op2)
895 /* if they have registers in common */
896 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
899 sym1 = OP_SYMBOL(op1);
900 sym2 = OP_SYMBOL(op2);
902 if (sym1->nRegs == 0 || sym2->nRegs == 0)
905 for (i = 0 ; i < sym1->nRegs ; i++) {
910 for (j = 0 ; j < sym2->nRegs ;j++ ) {
914 if (sym2->regs[j] == sym1->regs[i])
922 /*-----------------------------------------------------------------*/
923 /* operandsEqu - equivalent */
924 /*-----------------------------------------------------------------*/
925 static bool operandsEqu ( operand *op1, operand *op2)
929 /* if they not symbols */
930 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
933 sym1 = OP_SYMBOL(op1);
934 sym2 = OP_SYMBOL(op2);
936 /* if both are itemps & one is spilt
937 and the other is not then false */
938 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
939 sym1->isspilt != sym2->isspilt )
942 /* if they are the same */
946 if (sym1->rname[0] && sym2->rname[0]
947 && strcmp (sym1->rname, sym2->rname) == 0)
951 /* if left is a tmp & right is not */
955 (sym1->usl.spillLoc == sym2))
962 (sym2->usl.spillLoc == sym1))
968 /*-----------------------------------------------------------------*/
969 /* pic16_sameRegs - two asmops have the same registers */
970 /*-----------------------------------------------------------------*/
971 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
978 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
979 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
981 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
983 if (aop1->type != AOP_REG ||
984 aop2->type != AOP_REG )
987 if (aop1->size != aop2->size )
990 for (i = 0 ; i < aop1->size ; i++ )
991 if (aop1->aopu.aop_reg[i] !=
992 aop2->aopu.aop_reg[i] )
998 /*-----------------------------------------------------------------*/
999 /* pic16_aopOp - allocates an asmop for an operand : */
1000 /*-----------------------------------------------------------------*/
1001 void pic16_aopOp (operand *op, iCode *ic, bool result)
1010 // DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1012 /* if this a literal */
1013 if (IS_OP_LITERAL(op)) {
1014 op->aop = aop = newAsmop(AOP_LIT);
1015 aop->aopu.aop_lit = op->operand.valOperand;
1016 aop->size = getSize(operandType(op));
1021 sym_link *type = operandType(op);
1023 if(IS_PTR_CONST(type))
1025 if(IS_CODEPTR(type))
1027 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1030 /* if already has a asmop then continue */
1034 /* if the underlying symbol has a aop */
1035 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1036 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1037 op->aop = OP_SYMBOL(op)->aop;
1041 /* if this is a true symbol */
1042 if (IS_TRUE_SYMOP(op)) {
1043 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1044 op->aop = aopForSym(ic, op, result);
1048 /* this is a temporary : this has
1054 e) can be a return use only */
1056 sym = OP_SYMBOL(op);
1058 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
1059 /* if the type is a conditional */
1060 if (sym->regType == REG_CND) {
1061 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1066 /* if it is spilt then two situations
1068 b) has a spill location */
1069 if (sym->isspilt || sym->nRegs == 0) {
1071 DEBUGpic16_emitcode(";","%d",__LINE__);
1072 /* rematerialize it NOW */
1075 sym->aop = op->aop = aop =
1077 aop->size = getSize(sym->type);
1078 //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1085 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1086 aop->size = getSize(sym->type);
1087 for ( i = 0 ; i < 1 ; i++ ) {
1088 aop->aopu.aop_str[i] = accUse[i];
1089 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1091 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1092 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1100 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1101 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1102 //pic16_allocDirReg (IC_LEFT(ic));
1103 aop->size = getSize(sym->type);
1108 aop = op->aop = sym->aop = newAsmop(AOP_STR);
1109 aop->size = getSize(sym->type);
1110 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1111 aop->aopu.aop_str[i] = fReturn[i];
1113 DEBUGpic16_emitcode(";","%d",__LINE__);
1117 /* else spill location */
1118 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1119 /* force a new aop if sizes differ */
1120 sym->usl.spillLoc->aop = NULL;
1122 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1123 __FUNCTION__,__LINE__,
1124 sym->usl.spillLoc->rname,
1125 sym->rname, sym->usl.spillLoc->offset);
1127 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1128 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1129 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1131 sym->usl.spillLoc->offset, op);
1132 aop->size = getSize(sym->type);
1138 sym_link *type = operandType(op);
1140 if(IS_PTR_CONST(type))
1142 if(IS_CODEPTR(type))
1144 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1147 /* must be in a register */
1148 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1149 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1150 aop->size = sym->nRegs;
1151 for ( i = 0 ; i < sym->nRegs ;i++)
1152 aop->aopu.aop_reg[i] = sym->regs[i];
1155 /*-----------------------------------------------------------------*/
1156 /* pic16_freeAsmop - free up the asmop given to an operand */
1157 /*----------------------------------------------------------------*/
1158 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1175 /* depending on the asmop type only three cases need work AOP_RO
1176 , AOP_R1 && AOP_STK */
1178 switch (aop->type) {
1180 if (_G.fsr0Pushed ) {
1182 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1183 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1184 // pic16_emitcode ("pop","ar0");
1188 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1192 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1198 pic16_emitcode ("pop","ar0");
1202 bitVectUnSetBit(ic->rUsed,R0_IDX);
1208 pic16_emitcode ("pop","ar1");
1212 bitVectUnSetBit(ic->rUsed,R1_IDX);
1218 int stk = aop->aopu.aop_stk + aop->size;
1219 bitVectUnSetBit(ic->rUsed,R0_IDX);
1220 bitVectUnSetBit(ic->rUsed,R1_IDX);
1222 getFreePtr(ic,&aop,FALSE);
1224 if (options.stack10bit)
1226 /* I'm not sure what to do here yet... */
1229 "*** Warning: probably generating bad code for "
1230 "10 bit stack mode.\n");
1234 pic16_emitcode ("mov","a,_bp");
1235 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1236 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1238 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1242 pic16_emitcode("pop","acc");
1243 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1245 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1248 pic16_freeAsmop(op,NULL,ic,TRUE);
1250 pic16_emitcode("pop","ar0");
1255 pic16_emitcode("pop","ar1");
1263 /* all other cases just dealloc */
1267 OP_SYMBOL(op)->aop = NULL;
1268 /* if the symbol has a spill */
1270 SPIL_LOC(op)->aop = NULL;
1275 /*-----------------------------------------------------------------*/
1276 /* pic16_aopGet - for fetching value of the aop */
1277 /*-----------------------------------------------------------------*/
1278 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1283 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1285 /* offset is greater than size then zero */
1286 if (offset > (aop->size - 1) &&
1287 aop->type != AOP_LIT)
1290 /* depending on type */
1291 switch (aop->type) {
1295 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1296 rs = Safe_calloc(1, strlen(s)+1);
1301 /* if we need to increment it */
1302 while (offset > aop->coff)
1304 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1308 while (offset < aop->coff)
1310 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1316 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1317 return (dname ? "acc" : "a");
1319 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1320 rs = Safe_calloc (1, strlen (s) + 1);
1328 sprintf (s,"%s",aop->aopu.aop_immd);
1331 sprintf(s,"(%s >> %d)",
1336 aop->aopu.aop_immd);
1337 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1338 rs = Safe_calloc(1,strlen(s)+1);
1344 sprintf(s,"(%s + %d)",
1347 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1349 sprintf(s,"%s",aop->aopu.aop_dir);
1350 rs = Safe_calloc(1,strlen(s)+1);
1356 // return aop->aopu.aop_reg[offset]->dname;
1358 return aop->aopu.aop_reg[offset]->name;
1361 //pic16_emitcode(";","%d",__LINE__);
1362 return aop->aopu.aop_dir;
1365 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1366 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1368 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1369 rs = Safe_strdup("WREG");
1373 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1374 rs = Safe_calloc(1,strlen(s)+1);
1379 aop->coff = offset ;
1380 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1383 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1385 return aop->aopu.aop_str[offset];
1389 pCodeOp *pcop = aop->aopu.pcop;
1390 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1392 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1393 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1394 sprintf(s,"%s", pcop->name);
1396 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1399 rs = Safe_calloc(1,strlen(s)+1);
1404 // pCodeOp *pcop = aop->aop
1409 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1410 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1411 "aopget got unsupported aop->type");
1416 /*-----------------------------------------------------------------*/
1417 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1418 /*-----------------------------------------------------------------*/
1419 pCodeOp *pic16_popGetTempReg(void)
1424 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1429 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1430 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1431 PCOR(pcop)->r->wasUsed=1;
1432 PCOR(pcop)->r->isFree=0;
1434 /* push value on stack */
1435 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1443 /*-----------------------------------------------------------------*/
1444 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1445 /*-----------------------------------------------------------------*/
1446 void pic16_popReleaseTempReg(pCodeOp *pcop)
1448 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1450 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1451 PCOR(pcop)->r->isFree = 1;
1453 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1456 /*-----------------------------------------------------------------*/
1457 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1458 /*-----------------------------------------------------------------*/
1459 pCodeOp *pic16_popGetLabel(unsigned int key)
1462 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1467 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1470 /*-----------------------------------------------------------------*/
1471 /* pic16_popCopyReg - copy a pcode operator */
1472 /*-----------------------------------------------------------------*/
1473 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1477 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1478 pcor->pcop.type = pc->pcop.type;
1480 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1481 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1483 pcor->pcop.name = NULL;
1486 pcor->rIdx = pc->rIdx;
1489 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1494 /*-----------------------------------------------------------------*/
1495 /* pic16_popGetLit - asm operator to pcode operator conversion */
1496 /*-----------------------------------------------------------------*/
1497 pCodeOp *pic16_popGetLit(unsigned int lit)
1499 return pic16_newpCodeOpLit(lit);
1502 /*-----------------------------------------------------------------*/
1503 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1504 /*-----------------------------------------------------------------*/
1505 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1507 return pic16_newpCodeOpLit2(lit, arg2);
1511 /*-----------------------------------------------------------------*/
1512 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1513 /*-----------------------------------------------------------------*/
1514 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1516 return pic16_newpCodeOpImmd(name, offset,index, 0);
1520 /*-----------------------------------------------------------------*/
1521 /* pic16_popGet - asm operator to pcode operator conversion */
1522 /*-----------------------------------------------------------------*/
1523 pCodeOp *pic16_popGetWithString(char *str)
1529 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1533 pcop = pic16_newpCodeOp(str,PO_STR);
1538 /*-----------------------------------------------------------------*/
1539 /* pic16_popRegFromString - */
1540 /*-----------------------------------------------------------------*/
1541 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1544 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1545 pcop->type = PO_DIR;
1547 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1548 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1553 pcop->name = Safe_calloc(1,strlen(str)+1);
1554 strcpy(pcop->name,str);
1556 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1558 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1559 if(PCOR(pcop)->r == NULL) {
1560 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1561 // __FUNCTION__, __LINE__, str, size, offset);
1564 // PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1565 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1567 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1569 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d",__LINE__,pcop->name,size,offset);
1571 PCOR(pcop)->instance = offset;
1576 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1580 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1582 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1583 PCOR(pcop)->rIdx = rIdx;
1584 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1586 PCOR(pcop)->r->isFree = 0;
1587 PCOR(pcop)->r->wasUsed = 1;
1589 pcop->type = PCOR(pcop)->r->pc_type;
1594 /*---------------------------------------------------------------------------------*/
1595 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1597 /*---------------------------------------------------------------------------------*/
1598 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1603 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1605 /* comment the following check, so errors to throw up */
1606 // if(!pcop2)return NULL;
1608 temp = pic16_popGet(aop_dst, offset);
1609 pcop2->pcop2 = temp;
1616 /*--------------------------------------------------------------------------------.-*/
1617 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1618 /* VR 030601 , adapted by Hans Dorn */
1619 /*--------------------------------------------------------------------------------.-*/
1620 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1624 pcop2 = (pCodeOpReg2 *)src;
1632 /*---------------------------------------------------------------------------------*/
1633 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1634 /* movff instruction */
1635 /*---------------------------------------------------------------------------------*/
1636 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1641 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1642 pcop2->pcop2 = pic16_popCopyReg(dst);
1644 /* the pCodeOp may be already allocated */
1645 pcop2 = (pCodeOpReg2 *)(src);
1646 pcop2->pcop2 = (pCodeOp *)(dst);
1653 /*-----------------------------------------------------------------*/
1654 /* pic16_popGet - asm operator to pcode operator conversion */
1655 /*-----------------------------------------------------------------*/
1656 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1658 //char *s = buffer ;
1662 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1663 /* offset is greater than
1666 // if (offset > (aop->size - 1) &&
1667 // aop->type != AOP_LIT)
1668 // return NULL; //zero;
1670 /* depending on type */
1671 switch (aop->type) {
1677 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1678 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1685 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1686 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
1687 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1688 PCOR(pcop)->r->wasUsed = 1;
1689 PCOR(pcop)->r->isFree = 0;
1691 PCOR(pcop)->instance = offset;
1692 pcop->type = PCOR(pcop)->r->pc_type;
1696 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1697 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1701 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1703 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1705 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1707 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1708 PCOR(pcop)->rIdx = rIdx;
1709 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1710 PCOR(pcop)->r->wasUsed=1;
1711 PCOR(pcop)->r->isFree=0;
1713 PCOR(pcop)->instance = offset;
1714 pcop->type = PCOR(pcop)->r->pc_type;
1715 // rs = aop->aopu.aop_reg[offset]->name;
1716 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1720 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1721 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1727 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1728 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1732 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1734 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1736 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1737 // pcop->type = PO_GPR_REGISTER;
1738 PCOR(pcop)->rIdx = rIdx;
1739 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
1740 PCOR(pcop)->r->wasUsed=1;
1741 PCOR(pcop)->r->isFree=0;
1743 PCOR(pcop)->instance = offset;
1744 pcop->type = PCOR(pcop)->r->pc_type;
1745 rs = aop->aopu.aop_reg[offset]->name;
1746 DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1751 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1753 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1754 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1755 //if(PCOR(pcop)->r == NULL)
1756 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1760 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1761 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1764 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1765 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1768 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1769 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1770 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1771 pcop->type = PCOR(pcop)->r->pc_type;
1772 pcop->name = PCOR(pcop)->r->name;
1778 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1780 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1781 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1783 switch( aop->aopu.pcop->type ) {
1784 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1785 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1787 assert( 0 ); /* should never reach here */;
1790 PCOI(pcop)->offset = offset;
1795 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1796 "pic16_popGet got unsupported aop->type");
1799 /*-----------------------------------------------------------------*/
1800 /* pic16_aopPut - puts a string for a aop */
1801 /*-----------------------------------------------------------------*/
1802 void pic16_aopPut (asmop *aop, char *s, int offset)
1807 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1809 if (aop->size && offset > ( aop->size - 1)) {
1810 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1811 "pic16_aopPut got offset > aop->size");
1815 /* will assign value to value */
1816 /* depending on where it is ofcourse */
1817 switch (aop->type) {
1820 sprintf(d,"(%s + %d)",
1821 aop->aopu.aop_dir,offset);
1822 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1825 sprintf(d,"%s",aop->aopu.aop_dir);
1828 DEBUGpic16_emitcode(";","%d",__LINE__);
1830 pic16_emitcode("movf","%s,w",s);
1831 pic16_emitcode("movwf","%s",d);
1834 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1835 if(offset >= aop->size) {
1836 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1839 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1842 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1849 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1850 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1853 strcmp(s,"r0") == 0 ||
1854 strcmp(s,"r1") == 0 ||
1855 strcmp(s,"r2") == 0 ||
1856 strcmp(s,"r3") == 0 ||
1857 strcmp(s,"r4") == 0 ||
1858 strcmp(s,"r5") == 0 ||
1859 strcmp(s,"r6") == 0 ||
1860 strcmp(s,"r7") == 0 )
1861 pic16_emitcode("mov","%s,%s ; %d",
1862 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1866 if(strcmp(s,"W")==0 )
1867 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
1869 pic16_emitcode("movwf","%s",
1870 aop->aopu.aop_reg[offset]->name);
1872 if(strcmp(s,zero)==0) {
1873 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1875 } else if(strcmp(s,"W")==0) {
1876 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1877 pcop->type = PO_GPR_REGISTER;
1879 PCOR(pcop)->rIdx = -1;
1880 PCOR(pcop)->r = NULL;
1882 DEBUGpic16_emitcode(";","%d",__LINE__);
1883 pcop->name = Safe_strdup(s);
1884 pic16_emitpcode(POC_MOVFW,pcop);
1885 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1886 } else if(strcmp(s,one)==0) {
1887 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1888 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1890 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1898 if (aop->type == AOP_DPTR2)
1904 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1905 "pic16_aopPut writting to code space");
1909 while (offset > aop->coff) {
1911 pic16_emitcode ("inc","dptr");
1914 while (offset < aop->coff) {
1916 pic16_emitcode("lcall","__decdptr");
1921 /* if not in accumulater */
1924 pic16_emitcode ("movx","@dptr,a");
1926 if (aop->type == AOP_DPTR2)
1934 while (offset > aop->coff) {
1936 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1938 while (offset < aop->coff) {
1940 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1946 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1951 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1953 if (strcmp(s,"r0") == 0 ||
1954 strcmp(s,"r1") == 0 ||
1955 strcmp(s,"r2") == 0 ||
1956 strcmp(s,"r3") == 0 ||
1957 strcmp(s,"r4") == 0 ||
1958 strcmp(s,"r5") == 0 ||
1959 strcmp(s,"r6") == 0 ||
1960 strcmp(s,"r7") == 0 ) {
1962 sprintf(buffer,"a%s",s);
1963 pic16_emitcode("mov","@%s,%s",
1964 aop->aopu.aop_ptr->name,buffer);
1966 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1971 if (strcmp(s,"a") == 0)
1972 pic16_emitcode("push","acc");
1974 pic16_emitcode("push","%s",s);
1979 /* if bit variable */
1980 if (!aop->aopu.aop_dir) {
1981 pic16_emitcode("clr","a");
1982 pic16_emitcode("rlc","a");
1985 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1988 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1991 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1993 lbl = newiTempLabel(NULL);
1995 if (strcmp(s,"a")) {
1998 pic16_emitcode("clr","c");
1999 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2000 pic16_emitcode("cpl","c");
2001 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2002 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2009 if (strcmp(aop->aopu.aop_str[offset],s))
2010 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2015 if (!offset && (strcmp(s,"acc") == 0))
2018 if (strcmp(aop->aopu.aop_str[offset],s))
2019 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2023 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2024 "pic16_aopPut got unsupported aop->type");
2030 /*-----------------------------------------------------------------*/
2031 /* mov2w - generate either a MOVLW or MOVFW based operand type */
2032 /*-----------------------------------------------------------------*/
2033 static void mov2w (asmop *aop, int offset)
2039 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2042 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2044 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2049 /* push pcop into stack */
2050 void pic16_pushpCodeOp(pCodeOp *pcop)
2052 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2053 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2056 /* pop pcop from stack */
2057 void pic16_poppCodeOp(pCodeOp *pcop)
2059 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2063 /*-----------------------------------------------------------------*/
2064 /* pushw - pushes wreg to stack */
2065 /*-----------------------------------------------------------------*/
2068 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2069 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2073 /*-----------------------------------------------------------------*/
2074 /* pushaop - pushes aop to stack */
2075 /*-----------------------------------------------------------------*/
2076 void pushaop(asmop *aop, int offset)
2078 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2079 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2082 /*-----------------------------------------------------------------*/
2083 /* popaop - pops aop from stack */
2084 /*-----------------------------------------------------------------*/
2085 void popaop(asmop *aop, int offset)
2087 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2088 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2091 void popaopidx(asmop *aop, int offset, int index)
2095 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2097 if(STACK_MODEL_LARGE)ofs++;
2099 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2100 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2103 /*-----------------------------------------------------------------*/
2104 /* reAdjustPreg - points a register back to where it should */
2105 /*-----------------------------------------------------------------*/
2106 static void reAdjustPreg (asmop *aop)
2110 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2112 if ((size = aop->size) <= 1)
2115 switch (aop->type) {
2119 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2123 if (aop->type == AOP_DPTR2)
2129 pic16_emitcode("lcall","__decdptr");
2132 if (aop->type == AOP_DPTR2)
2144 /*-----------------------------------------------------------------*/
2145 /* opIsGptr: returns non-zero if the passed operand is */
2146 /* a generic pointer type. */
2147 /*-----------------------------------------------------------------*/
2148 static int opIsGptr(operand *op)
2150 sym_link *type = operandType(op);
2152 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2153 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2161 /*-----------------------------------------------------------------*/
2162 /* pic16_getDataSize - get the operand data size */
2163 /*-----------------------------------------------------------------*/
2164 int pic16_getDataSize(operand *op)
2166 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2169 return AOP_SIZE(op);
2171 // tsd- in the pic port, the genptr size is 1, so this code here
2172 // fails. ( in the 8051 port, the size was 4).
2175 size = AOP_SIZE(op);
2176 if (size == GPTRSIZE)
2178 sym_link *type = operandType(op);
2179 if (IS_GENPTR(type))
2181 /* generic pointer; arithmetic operations
2182 * should ignore the high byte (pointer type).
2185 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2192 /*-----------------------------------------------------------------*/
2193 /* pic16_outAcc - output Acc */
2194 /*-----------------------------------------------------------------*/
2195 void pic16_outAcc(operand *result)
2198 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2199 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2202 size = pic16_getDataSize(result);
2204 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2207 /* unsigned or positive */
2209 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2214 /*-----------------------------------------------------------------*/
2215 /* pic16_outBitC - output a bit C */
2216 /* Move to result the value of Carry flag -- VR */
2217 /*-----------------------------------------------------------------*/
2218 void pic16_outBitC(operand *result)
2222 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2223 /* if the result is bit */
2224 if (AOP_TYPE(result) == AOP_CRY) {
2225 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2226 pic16_aopPut(AOP(result),"c",0);
2229 i = AOP_SIZE(result);
2231 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2233 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2236 pic16_emitcode("clr","a ; %d", __LINE__);
2237 pic16_emitcode("rlc","a");
2238 pic16_outAcc(result);
2243 /*-----------------------------------------------------------------*/
2244 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2245 /*-----------------------------------------------------------------*/
2246 void pic16_toBoolean(operand *oper)
2248 int size = AOP_SIZE(oper) - 1;
2251 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2253 if ( AOP_TYPE(oper) != AOP_ACC) {
2254 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2257 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2262 #if !defined(GEN_Not)
2263 /*-----------------------------------------------------------------*/
2264 /* genNot - generate code for ! operation */
2265 /*-----------------------------------------------------------------*/
2266 static void pic16_genNot (iCode *ic)
2271 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2272 /* assign asmOps to operand & result */
2273 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2274 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2276 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2277 /* if in bit space then a special case */
2278 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2279 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2280 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2281 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2283 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2284 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2285 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2290 size = AOP_SIZE(IC_LEFT(ic));
2292 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2293 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2294 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2297 pic16_toBoolean(IC_LEFT(ic));
2299 tlbl = newiTempLabel(NULL);
2300 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2301 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2302 pic16_outBitC(IC_RESULT(ic));
2305 /* release the aops */
2306 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2307 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2312 #if !defined(GEN_Cpl)
2313 /*-----------------------------------------------------------------*/
2314 /* genCpl - generate code for complement */
2315 /*-----------------------------------------------------------------*/
2316 static void pic16_genCpl (iCode *ic)
2322 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2323 /* assign asmOps to operand & result */
2324 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2325 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2327 /* if both are in bit space then
2329 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2330 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2332 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2333 pic16_emitcode("cpl","c");
2334 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2338 size = AOP_SIZE(IC_RESULT(ic));
2341 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2343 pic16_emitcode("cpl","a");
2344 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2346 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2347 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2349 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2350 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2358 /* release the aops */
2359 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2360 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2364 /*-----------------------------------------------------------------*/
2365 /* genUminusFloat - unary minus for floating points */
2366 /*-----------------------------------------------------------------*/
2367 static void genUminusFloat(operand *op,operand *result)
2369 int size ,offset =0 ;
2372 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2373 /* for this we just need to flip the
2374 first it then copy the rest in place */
2375 size = AOP_SIZE(op) - 1;
2376 l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2380 pic16_emitcode("cpl","acc.7");
2381 pic16_aopPut(AOP(result),"a",3);
2384 pic16_aopPut(AOP(result),
2385 pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2391 /*-----------------------------------------------------------------*/
2392 /* genUminus - unary minus code generation */
2393 /*-----------------------------------------------------------------*/
2394 static void genUminus (iCode *ic)
2397 sym_link *optype, *rtype;
2399 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2402 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2403 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2405 /* if both in bit space then special case */
2406 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2407 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2409 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2410 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2411 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2416 optype = operandType(IC_LEFT(ic));
2417 rtype = operandType(IC_RESULT(ic));
2419 /* if float then do float stuff */
2420 if (IS_FLOAT(optype)) {
2421 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2425 /* otherwise subtract from zero by taking the 2's complement */
2426 size = AOP_SIZE(IC_LEFT(ic));
2428 for(i=0; i<size; i++) {
2429 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2430 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)),i));
2432 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2433 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2437 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2438 for(i=1; i<size; i++) {
2440 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2444 /* release the aops */
2445 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2446 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2449 /*-----------------------------------------------------------------*/
2450 /* saveRegisters - will look for a call and save the registers */
2451 /*-----------------------------------------------------------------*/
2452 static void saveRegisters(iCode *lic)
2459 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2461 for (ic = lic ; ic ; ic = ic->next)
2462 if (ic->op == CALL || ic->op == PCALL)
2466 fprintf(stderr,"found parameter push with no function call\n");
2470 /* if the registers have been saved already then
2472 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2475 /* find the registers in use at this time
2476 and push them away to safety */
2477 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2481 if (options.useXstack) {
2482 if (bitVectBitValue(rsave,R0_IDX))
2483 pic16_emitcode("mov","b,r0");
2484 pic16_emitcode("mov","r0,%s",spname);
2485 for (i = 0 ; i < pic16_nRegs ; i++) {
2486 if (bitVectBitValue(rsave,i)) {
2488 pic16_emitcode("mov","a,b");
2490 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2491 pic16_emitcode("movx","@r0,a");
2492 pic16_emitcode("inc","r0");
2495 pic16_emitcode("mov","%s,r0",spname);
2496 if (bitVectBitValue(rsave,R0_IDX))
2497 pic16_emitcode("mov","r0,b");
2499 //for (i = 0 ; i < pic16_nRegs ; i++) {
2500 // if (bitVectBitValue(rsave,i))
2501 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2504 dtype = operandType(IC_LEFT(ic));
2505 if (currFunc && dtype &&
2506 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2507 IFFUNC_ISISR(currFunc->type) &&
2510 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2513 /*-----------------------------------------------------------------*/
2514 /* unsaveRegisters - pop the pushed registers */
2515 /*-----------------------------------------------------------------*/
2516 static void unsaveRegisters (iCode *ic)
2521 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2522 /* find the registers in use at this time
2523 and push them away to safety */
2524 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2527 if (options.useXstack) {
2528 pic16_emitcode("mov","r0,%s",spname);
2529 for (i = pic16_nRegs ; i >= 0 ; i--) {
2530 if (bitVectBitValue(rsave,i)) {
2531 pic16_emitcode("dec","r0");
2532 pic16_emitcode("movx","a,@r0");
2534 pic16_emitcode("mov","b,a");
2536 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2540 pic16_emitcode("mov","%s,r0",spname);
2541 if (bitVectBitValue(rsave,R0_IDX))
2542 pic16_emitcode("mov","r0,b");
2544 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2545 // if (bitVectBitValue(rsave,i))
2546 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2552 /*-----------------------------------------------------------------*/
2554 /*-----------------------------------------------------------------*/
2555 static void pushSide(operand * oper, int size)
2558 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2560 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2561 if (AOP_TYPE(oper) != AOP_REG &&
2562 AOP_TYPE(oper) != AOP_DIR &&
2564 pic16_emitcode("mov","a,%s",l);
2565 pic16_emitcode("push","acc");
2567 pic16_emitcode("push","%s",l);
2572 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2574 // (AOP(left)->aopu.pcop->type == PO_DIR)?
2576 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2577 pic16_emitpcode(POC_MOVFW, src);
2578 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2580 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2581 src, pic16_popGet(AOP(op), offset)));
2586 /*-----------------------------------------------------------------*/
2587 /* assignResultValue - assign results to oper, rescall==1 is */
2588 /* called from genCall() or genPCall() */
2589 /*-----------------------------------------------------------------*/
2590 static void assignResultValue(operand * oper, int rescall)
2592 int size = AOP_SIZE(oper);
2594 DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2595 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2598 /* assign result from a call/pcall function() */
2600 /* function results are stored in a special order,
2601 * see top of file with Function return policy, or manual */
2604 /* 8-bits, result in WREG */
2605 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2608 /* 16-bits, result in PRODL:WREG */
2609 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2613 /* 24-bits, result in PRODH:PRODL:WREG */
2614 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2618 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2619 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2622 /* >32-bits, result on stack, and FSR0 points to beginning.
2623 * Fix stack when done */
2626 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2627 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2629 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2634 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2635 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2636 if(STACK_MODEL_LARGE) {
2638 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2642 if(!GpsuedoStkPtr) {
2643 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2644 /* The last byte in the assignment is in W */
2646 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2651 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2652 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2654 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2660 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2662 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2672 /*-----------------------------------------------------------------*/
2673 /* genIpush - genrate code for pushing this gets a little complex */
2674 /*-----------------------------------------------------------------*/
2675 static void genIpush (iCode *ic)
2679 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2682 pic16_aopOp(IC_LEFT(ic), ic, FALSE);
2685 size = AOP_SIZE( IC_LEFT(ic) );
2688 mov2w( AOP(IC_LEFT(ic)), offset );
2694 int size, offset = 0 ;
2698 /* if this is not a parm push : ie. it is spill push
2699 and spill push is always done on the local stack */
2700 if (!ic->parmPush) {
2702 /* and the item is spilt then do nothing */
2703 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2706 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2707 size = AOP_SIZE(IC_LEFT(ic));
2708 /* push it on the stack */
2710 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2715 pic16_emitcode("push","%s",l);
2720 /* this is a paramter push: in this case we call
2721 the routine to find the call and save those
2722 registers that need to be saved */
2725 /* then do the push */
2726 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2729 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2730 size = AOP_SIZE(IC_LEFT(ic));
2733 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2734 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2735 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2737 pic16_emitcode("mov","a,%s",l);
2738 pic16_emitcode("push","acc");
2740 pic16_emitcode("push","%s",l);
2743 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2747 /*-----------------------------------------------------------------*/
2748 /* genIpop - recover the registers: can happen only for spilling */
2749 /*-----------------------------------------------------------------*/
2750 static void genIpop (iCode *ic)
2752 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2757 /* if the temp was not pushed then */
2758 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2761 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2762 size = AOP_SIZE(IC_LEFT(ic));
2765 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2768 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2772 /*-----------------------------------------------------------------*/
2773 /* unsaverbank - restores the resgister bank from stack */
2774 /*-----------------------------------------------------------------*/
2775 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2777 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2783 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2785 if (options.useXstack) {
2787 r = getFreePtr(ic,&aop,FALSE);
2790 pic16_emitcode("mov","%s,_spx",r->name);
2791 pic16_emitcode("movx","a,@%s",r->name);
2792 pic16_emitcode("mov","psw,a");
2793 pic16_emitcode("dec","%s",r->name);
2796 pic16_emitcode ("pop","psw");
2799 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2800 if (options.useXstack) {
2801 pic16_emitcode("movx","a,@%s",r->name);
2802 //pic16_emitcode("mov","(%s+%d),a",
2803 // regspic16[i].base,8*bank+regspic16[i].offset);
2804 pic16_emitcode("dec","%s",r->name);
2807 pic16_emitcode("pop",""); //"(%s+%d)",
2808 //regspic16[i].base,8*bank); //+regspic16[i].offset);
2811 if (options.useXstack) {
2813 pic16_emitcode("mov","_spx,%s",r->name);
2814 pic16_freeAsmop(NULL,aop,ic,TRUE);
2820 /*-----------------------------------------------------------------*/
2821 /* saverbank - saves an entire register bank on the stack */
2822 /*-----------------------------------------------------------------*/
2823 static void saverbank (int bank, iCode *ic, bool pushPsw)
2825 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2831 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2832 if (options.useXstack) {
2835 r = getFreePtr(ic,&aop,FALSE);
2836 pic16_emitcode("mov","%s,_spx",r->name);
2840 for (i = 0 ; i < pic16_nRegs ;i++) {
2841 if (options.useXstack) {
2842 pic16_emitcode("inc","%s",r->name);
2843 //pic16_emitcode("mov","a,(%s+%d)",
2844 // regspic16[i].base,8*bank+regspic16[i].offset);
2845 pic16_emitcode("movx","@%s,a",r->name);
2847 pic16_emitcode("push","");// "(%s+%d)",
2848 //regspic16[i].base,8*bank+regspic16[i].offset);
2852 if (options.useXstack) {
2853 pic16_emitcode("mov","a,psw");
2854 pic16_emitcode("movx","@%s,a",r->name);
2855 pic16_emitcode("inc","%s",r->name);
2856 pic16_emitcode("mov","_spx,%s",r->name);
2857 pic16_freeAsmop (NULL,aop,ic,TRUE);
2860 pic16_emitcode("push","psw");
2862 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2870 /*-----------------------------------------------------------------*/
2871 /* genCall - generates a call statement */
2872 /*-----------------------------------------------------------------*/
2873 static void genCall (iCode *ic)
2878 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2880 /* if caller saves & we have not saved then */
2884 /* if we are calling a function that is not using
2885 * the same register bank then we need to save the
2886 * destination registers on the stack */
2887 dtype = operandType(IC_LEFT(ic));
2888 if (currFunc && dtype &&
2889 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2890 IFFUNC_ISISR(currFunc->type) &&
2893 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2896 /* initialise stackParms for IPUSH pushes */
2897 // stackParms = psuedoStkPtr;
2898 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2900 /* if send set is not empty the assign */
2904 /* For the Pic port, there is no data stack.
2905 * So parameters passed to functions are stored
2906 * in registers. (The pCode optimizer will get
2907 * rid of most of these :). */
2909 int psuedoStkPtr=-1;
2910 int firstTimeThruLoop = 1;
2912 _G.sendSet = reverseSet(_G.sendSet);
2914 /* First figure how many parameters are getting passed */
2915 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2916 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2917 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2918 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2921 stackParms = psuedoStkPtr;
2923 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2924 int size, offset = 0;
2926 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2927 size = AOP_SIZE(IC_LEFT(sic));
2930 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2931 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2932 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2934 if(!firstTimeThruLoop) {
2935 /* If this is not the first time we've been through the loop
2936 * then we need to save the parameter in a temporary
2937 * register. The last byte of the last parameter is
2941 --psuedoStkPtr; // sanity check
2944 firstTimeThruLoop=0;
2946 mov2w (AOP(IC_LEFT(sic)), offset);
2949 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2955 pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2956 OP_SYMBOL(IC_LEFT(ic))->rname :
2957 OP_SYMBOL(IC_LEFT(ic))->name));
2960 /* if we need assign a result value */
2961 if ((IS_ITEMP(IC_RESULT(ic)) &&
2962 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2963 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2964 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2967 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2970 assignResultValue(IC_RESULT(ic), 1);
2972 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2973 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2975 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2978 if(!stackParms && ic->parmBytes) {
2979 stackParms = ic->parmBytes;
2983 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2984 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2985 if(STACK_MODEL_LARGE) {
2987 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2991 /* adjust the stack for parameters if required */
2992 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2994 if (ic->parmBytes) {
2997 if (ic->parmBytes > 3) {
2998 pic16_emitcode("mov","a,%s",spname);
2999 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3000 pic16_emitcode("mov","%s,a",spname);
3002 for ( i = 0 ; i < ic->parmBytes ;i++)
3003 pic16_emitcode("dec","%s",spname);
3008 /* if register bank was saved then pop them */
3010 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3012 /* if we hade saved some registers then unsave them */
3013 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3014 unsaveRegisters (ic);
3020 /*-----------------------------------------------------------------*/ // patch 14
3021 /* genPcall - generates a call by pointer statement */
3022 /*-----------------------------------------------------------------*/
3024 // new version, created from genCall
3026 static void genPcall (iCode *ic)
3030 symbol *retlbl = newiTempLabel(NULL);
3031 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3033 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3035 /* if caller saves & we have not saved then */
3039 /* if we are calling a function that is not using
3040 * the same register bank then we need to save the
3041 * destination registers on the stack */
3042 dtype = operandType(IC_LEFT(ic));
3043 if (currFunc && dtype &&
3044 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
3045 IFFUNC_ISISR(currFunc->type) &&
3048 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3050 /* if send set is not empty the assign */
3054 /* For the Pic port, there is no data stack.
3055 * So parameters passed to functions are stored
3056 * in registers. (The pCode optimizer will get
3057 * rid of most of these :). */
3059 int psuedoStkPtr=-1;
3060 int firstTimeThruLoop = 1;
3062 _G.sendSet = reverseSet(_G.sendSet);
3064 /* First figure how many parameters are getting passed */
3065 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3066 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3067 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
3068 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
3071 stackParms = psuedoStkPtr;
3073 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3074 int size, offset = 0;
3076 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3077 size = AOP_SIZE(IC_LEFT(sic));
3080 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3081 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3082 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3084 if(!firstTimeThruLoop) {
3085 /* If this is not the first time we've been through the loop
3086 * then we need to save the parameter in a temporary
3087 * register. The last byte of the last parameter is
3091 --psuedoStkPtr; // sanity check
3094 firstTimeThruLoop=0;
3096 mov2w (AOP(IC_LEFT(sic)), offset);
3099 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3104 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3106 // push return address
3107 // push $ on return stack, then replace with retlbl
3109 pic16_emitpcodeNULLop(POC_PUSH);
3111 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3112 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3113 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3114 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3115 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3116 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3118 /* make the call by writing the pointer into pc */
3119 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3120 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3122 // note: MOVFF to PCL not allowed
3123 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3124 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3127 // pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key));
3128 // pic16_emitpcodeNULLop(POC_NOP);
3129 // pic16_emitpcodeNULLop(POC_NOP);
3131 /* return address is here: (X) */
3132 pic16_emitpLabelFORCE(retlbl->key);
3134 // pic16_emitpcodeNULLop(POC_NOP);
3136 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3139 /* if we need assign a result value */
3140 if ((IS_ITEMP(IC_RESULT(ic)) &&
3141 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3142 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
3143 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3146 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3149 assignResultValue(IC_RESULT(ic), 1);
3151 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3152 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3154 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3158 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3159 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3160 if(STACK_MODEL_LARGE) {
3162 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3166 /* adjust the stack for parameters if required */
3167 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3169 if (ic->parmBytes) {
3172 if (ic->parmBytes > 3) {
3173 pic16_emitcode("mov","a,%s",spname);
3174 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3175 pic16_emitcode("mov","%s,a",spname);
3177 for ( i = 0 ; i < ic->parmBytes ;i++)
3178 pic16_emitcode("dec","%s",spname);
3181 /* if register bank was saved then pop them */
3183 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3185 /* if we hade saved some registers then unsave them */
3186 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3187 unsaveRegisters (ic);
3192 // old version, kept for reference
3194 /*-----------------------------------------------------------------*/
3195 /* genPcall - generates a call by pointer statement */
3196 /*-----------------------------------------------------------------*/
3197 static void genPcall (iCode *ic)
3200 symbol *rlbl = newiTempLabel(NULL);
3203 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3204 /* if caller saves & we have not saved then */
3208 /* if we are calling a function that is not using
3209 the same register bank then we need to save the
3210 destination registers on the stack */
3211 dtype = operandType(IC_LEFT(ic));
3212 if (currFunc && dtype &&
3213 IFFUNC_ISISR(currFunc->type) &&
3214 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3215 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3218 /* push the return address on to the stack */
3219 pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3220 pic16_emitcode("push","acc");
3221 pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3222 pic16_emitcode("push","acc");
3224 if (options.model == MODEL_FLAT24)
3226 pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3227 pic16_emitcode("push","acc");
3230 /* now push the calling address */
3231 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3233 pushSide(IC_LEFT(ic), FPTRSIZE);
3235 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3237 /* if send set is not empty the assign */
3241 for (sic = setFirstItem(_G.sendSet) ; sic ;
3242 sic = setNextItem(_G.sendSet)) {
3243 int size, offset = 0;
3244 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3245 size = AOP_SIZE(IC_LEFT(sic));
3247 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3249 if (strcmp(l,fReturn[offset]))
3250 pic16_emitcode("mov","%s,%s",
3255 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3260 pic16_emitcode("ret","");
3261 pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3264 /* if we need assign a result value */
3265 if ((IS_ITEMP(IC_RESULT(ic)) &&
3266 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3267 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3268 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3271 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3274 assignResultValue(IC_RESULT(ic), 1);
3276 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3279 /* adjust the stack for parameters if
3281 if (ic->parmBytes) {
3283 if (ic->parmBytes > 3) {
3284 pic16_emitcode("mov","a,%s",spname);
3285 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3286 pic16_emitcode("mov","%s,a",spname);
3288 for ( i = 0 ; i < ic->parmBytes ;i++)
3289 pic16_emitcode("dec","%s",spname);
3293 /* if register bank was saved then unsave them */
3294 if (currFunc && dtype &&
3295 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3296 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3298 /* if we hade saved some registers then
3301 unsaveRegisters (ic);
3307 /*-----------------------------------------------------------------*/
3308 /* resultRemat - result is rematerializable */
3309 /*-----------------------------------------------------------------*/
3310 static int resultRemat (iCode *ic)
3312 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3313 if (SKIP_IC(ic) || ic->op == IFX)
3316 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3317 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3318 if (sym->remat && !POINTER_SET(ic))
3325 #if defined(__BORLANDC__) || defined(_MSC_VER)
3326 #define STRCASECMP stricmp
3328 #define STRCASECMP strcasecmp
3332 /*-----------------------------------------------------------------*/
3333 /* inExcludeList - return 1 if the string is in exclude Reg list */
3334 /*-----------------------------------------------------------------*/
3335 static bool inExcludeList(char *s)
3337 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3340 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3341 if (options.excludeRegs[i] &&
3342 STRCASECMP(options.excludeRegs[i],"none") == 0)
3345 for ( i = 0 ; options.excludeRegs[i]; i++) {
3346 if (options.excludeRegs[i] &&
3347 STRCASECMP(s,options.excludeRegs[i]) == 0)
3354 /*-----------------------------------------------------------------*/
3355 /* genFunction - generated code for function entry */
3356 /*-----------------------------------------------------------------*/
3357 static void genFunction (iCode *ic)
3362 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3364 pic16_labelOffset += (max_key+4);
3369 ftype = operandType(IC_LEFT(ic));
3370 sym = OP_SYMBOL(IC_LEFT(ic));
3372 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3373 /* create an absolute section at the interrupt vector:
3374 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3382 sym = OP_SYMBOL( IC_LEFT(ic));
3384 if(interrupts[i]->name
3385 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3392 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3393 __FILE__, __LINE__, sym->name);
3396 _G.interruptvector = found;
3399 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3400 asym = newSymbol(asymname, 0);
3402 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3403 pic16_addpBlock( apb );
3405 pic16_addpCode2pBlock(apb,
3406 pic16_newpCodeCharP(";-----------------------------------------"));
3409 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3411 pic16_addpCode2pBlock(apb,
3412 pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3414 /* mark the end of this tiny function */
3415 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3420 abSym = Safe_calloc(1, sizeof(absSym));
3421 abSym->name = Safe_strdup( asymname );
3423 switch( _G.interruptvector ) {
3424 case 0: abSym->address = 0x000000; break;
3425 case 1: abSym->address = 0x000008; break;
3426 case 2: abSym->address = 0x000018; break;
3429 /* relocate interrupt vectors if needed */
3430 abSym->address += pic16_options.ivt_loc;
3432 addSet(&absSymSet, abSym);
3437 /* create the function header */
3438 pic16_emitcode(";","-----------------------------------------");
3439 pic16_emitcode(";"," function %s",sym->name);
3440 pic16_emitcode(";","-----------------------------------------");
3442 pic16_emitcode("","%s:",sym->rname);
3443 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3449 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3450 if(!strcmp(ab->name, sym->name)) {
3451 pic16_pBlockConvert2Absolute(pb);
3458 if(IFFUNC_ISNAKED(ftype)) {
3459 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3463 /* if critical function then turn interrupts off */
3464 if (IFFUNC_ISCRITICAL(ftype))
3465 pic16_emitcode("clr","ea");
3467 /* if this is an interrupt service routine then
3468 * save acc, b, dpl, dph */
3469 if (IFFUNC_ISISR(sym->type)) {
3472 _G.usefastretfie = 1; /* use shadow registers by default */
3473 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3474 if(!(_G.interruptvector == 1)) {
3476 /* do not save WREG,STATUS,BSR for high priority interrupts
3477 * because they are stored in the hardware shadow registers already */
3478 _G.usefastretfie = 0;
3479 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3480 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3481 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3485 /* these should really be optimized somehow, because not all
3486 * interrupt handlers modify them */
3487 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3488 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3489 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3490 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3492 // pic16_pBlockConvert2ISR(pb);
3494 /* if any registers used */
3495 if (sym->regsUsed) {
3496 /* save the registers used */
3497 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3498 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3499 if (bitVectBitValue(sym->regsUsed,i)) {
3501 fprintf(stderr, "%s:%d function %s uses register %s\n",
3502 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3503 pic16_regWithIdx(i)->name);
3506 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3509 if(!pic16_regWithIdx(i)->wasUsed) {
3510 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3511 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3513 pic16_regWithIdx(i)->wasUsed = 1;
3519 /* emit code to setup stack frame if user enabled,
3520 * and function is not main() */
3522 // fprintf(stderr, "function name: %s\n", sym->name);
3523 if(strcmp(sym->name, "main")) {
3524 if(/*!options.ommitFramePtr || */sym->regsUsed) {
3525 /* setup the stack frame */
3526 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3527 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3528 if(STACK_MODEL_LARGE)
3529 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3533 /* if callee-save to be used for this function
3534 * then save the registers being used in this function */
3535 // if (IFFUNC_CALLEESAVES(sym->type))
3539 // fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3541 // pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3543 /* if any registers used */
3544 if (sym->regsUsed) {
3545 /* save the registers used */
3546 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3547 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3548 if (bitVectBitValue(sym->regsUsed,i)) {
3551 fprintf(stderr, "%s:%d function %s uses register %s (wasUsed: %d, %p)\n",
3552 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3553 pic16_regWithIdx(i)->name,
3554 pic16_regWithIdx(i)->wasUsed,
3555 pic16_regWithIdx(i));
3558 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3560 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3561 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3562 // &pic16_pc_postdec1, 0));
3566 if(!pic16_regWithIdx(i)->wasUsed) {
3567 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3568 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3570 pic16_regWithIdx(i)->wasUsed = 1;
3582 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3584 if (options.useXstack) {
3585 pic16_emitcode("mov","r0,%s",spname);
3586 pic16_emitcode("mov","a,_bp");
3587 pic16_emitcode("movx","@r0,a");
3588 pic16_emitcode("inc","%s",spname);
3590 /* set up the stack */
3591 pic16_emitcode ("push","_bp"); /* save the callers stack */
3593 pic16_emitcode ("mov","_bp,%s",spname);
3596 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3598 /* adjust the stack for the function */
3603 werror(W_STACK_OVERFLOW,sym->name);
3605 if (i > 3 && sym->recvSize < 4) {
3606 pic16_emitcode ("mov","a,sp");
3607 pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3608 pic16_emitcode ("mov","sp,a");
3611 pic16_emitcode("inc","sp");
3615 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3617 pic16_emitcode ("mov","a,_spx");
3618 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3619 pic16_emitcode ("mov","_spx,a");
3624 /*-----------------------------------------------------------------*/
3625 /* genEndFunction - generates epilogue for functions */
3626 /*-----------------------------------------------------------------*/
3627 static void genEndFunction (iCode *ic)
3629 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3631 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3633 if(IFFUNC_ISNAKED(sym->type)) {
3634 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3638 /* add code for ISCRITICAL */
3641 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3643 pic16_emitcode ("mov","%s,_bp",spname);
3647 /* if use external stack but some variables were
3648 added to the local stack then decrement the
3650 if (options.useXstack && sym->stack) {
3651 pic16_emitcode("mov","a,sp");
3652 pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3653 pic16_emitcode("mov","sp,a");
3658 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3659 if (options.useXstack) {
3660 pic16_emitcode("mov","r0,%s",spname);
3661 pic16_emitcode("movx","a,@r0");
3662 pic16_emitcode("mov","_bp,a");
3663 pic16_emitcode("dec","%s",spname);
3667 pic16_emitcode ("pop","_bp");
3672 if (IFFUNC_ISISR(sym->type)) {
3673 /* now we need to restore the registers */
3674 /* if any registers used */
3675 if (sym->regsUsed) {
3678 /* restore registers used */
3679 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3680 for ( i = sym->regsUsed->size; i >= 0; i--) {
3681 if (bitVectBitValue(sym->regsUsed,i)) {
3683 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3684 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3685 // pic16_regWithIdx(i)->name);
3687 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3689 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3690 // &pic16_pc_preinc1,
3691 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3697 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3698 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3699 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3700 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3702 if(!(_G.interruptvector == 1)) {
3703 /* do not restore interrupt vector for WREG,STATUS,BSR
3704 * for high priority interrupt, see genFunction */
3706 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3707 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3708 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3711 _G.interruptvector = 0; /* sanity check */
3713 // pic16_pBlockConvert2ISR(pb);
3716 /* if debug then send end of function */
3717 /* if (options.debug && currFunc) */
3719 debugFile->writeEndFunction (currFunc, ic, 1);
3722 if(_G.usefastretfie)
3723 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3725 pic16_emitpcodeNULLop(POC_RETFIE);
3726 _G.usefastretfie = 0;
3728 if (IFFUNC_ISCRITICAL(sym->type))
3729 pic16_emitcode("setb","ea");
3732 // pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3734 /* if any registers used */
3735 if (sym->regsUsed) {
3737 /* save the registers used */
3738 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3739 for ( i = sym->regsUsed->size; i >= 0; i--) {
3740 if (bitVectBitValue(sym->regsUsed,i)) {
3742 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3743 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3744 // pic16_regWithIdx(i)->name);
3746 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3748 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3749 // &pic16_pc_preinc1,
3750 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3757 // pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3758 /* if debug then send end of function */
3760 debugFile->writeEndFunction (currFunc, ic, 1);
3763 /* insert code to restore stack frame, if user enabled it
3764 * and function is not main() */
3767 if(strcmp(sym->name, "main")) {
3768 if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3769 /* restore stack frame */
3770 if(STACK_MODEL_LARGE)
3771 pic16_emitpcode(POC_MOVFF,
3772 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3773 pic16_emitpcode(POC_MOVFF,
3774 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3778 pic16_emitpcodeNULLop(POC_RETURN);
3780 /* Mark the end of a function */
3781 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3787 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3791 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3793 if(dest->type != PO_WREG)
3794 pic16_emitpcode(POC_MOVWF, dest);
3796 if(dest->type == PO_WREG && (offset == 0)) {
3797 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3801 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3802 pic16_popGet(AOP(op), offset), dest));
3806 /*-----------------------------------------------------------------*/
3807 /* genRet - generate code for return statement */
3808 /*-----------------------------------------------------------------*/
3809 static void genRet (iCode *ic)
3814 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3815 /* if we have no return value then
3816 * just generate the "ret" */
3821 /* we have something to return then
3822 * move the return value into place */
3823 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3824 size = AOP_SIZE(IC_LEFT(ic));
3828 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3829 // pic16_emitpcode(POC_MOVFF,
3830 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3833 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3834 // pic16_emitpcode(POC_MOVFF,
3835 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3838 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3839 // pic16_emitpcode(POC_MOVFF,
3840 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3843 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3845 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3846 // pic16_emitpcode(POC_MOVFF,
3847 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3850 /* >32-bits, setup stack and FSR0 */
3852 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3853 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3855 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3857 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3862 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3863 pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3865 if(STACK_MODEL_LARGE) {
3866 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3867 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3869 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3874 /* old code, left here for reference -- VR */
3878 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3880 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3881 pic16_emitpcomment("push %s",l);
3884 DEBUGpic16_emitcode(";", "%d", __LINE__);
3885 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3886 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3888 if (strcmp(fReturn[offset],l)) {
3889 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3890 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3891 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3893 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3897 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3907 if (strcmp(fReturn[pushed],"a"))
3908 pic16_emitcode("pop",fReturn[pushed]);
3910 pic16_emitcode("pop","acc");
3916 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3919 /* generate a jump to the return label
3920 * if the next is not the return statement */
3921 if (!(ic->next && ic->next->op == LABEL
3922 && IC_LABEL(ic->next) == returnLabel)) {
3924 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3925 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3929 /*-----------------------------------------------------------------*/
3930 /* genLabel - generates a label */
3931 /*-----------------------------------------------------------------*/
3932 static void genLabel (iCode *ic)
3936 /* special case never generate */
3937 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3938 if (IC_LABEL(ic) == entryLabel)
3941 pic16_emitpLabel(IC_LABEL(ic)->key);
3942 pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3945 /*-----------------------------------------------------------------*/
3946 /* genGoto - generates a goto */
3947 /*-----------------------------------------------------------------*/
3949 static void genGoto (iCode *ic)
3951 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3952 pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3956 /*-----------------------------------------------------------------*/
3957 /* genMultbits :- multiplication of bits */
3958 /*-----------------------------------------------------------------*/
3959 static void genMultbits (operand *left,
3963 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3965 if(!pic16_sameRegs(AOP(result),AOP(right)))
3966 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3968 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3969 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3970 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3975 /*-----------------------------------------------------------------*/
3976 /* genMultOneByte : 8 bit multiplication & division */
3977 /*-----------------------------------------------------------------*/
3978 static void genMultOneByte (operand *left,
3983 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3984 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3985 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3987 /* (if two literals, the value is computed before) */
3988 /* if one literal, literal on the right */
3989 if (AOP_TYPE(left) == AOP_LIT){
3995 /* size is already checked in genMult == 1 */
3996 // size = AOP_SIZE(result);
3998 if (AOP_TYPE(right) == AOP_LIT){
3999 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4000 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4001 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4002 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4004 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4005 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4006 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4007 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4010 pic16_genMult8X8_8 (left, right,result);
4013 /*-----------------------------------------------------------------*/
4014 /* genMultOneWord : 16 bit multiplication */
4015 /*-----------------------------------------------------------------*/
4016 static void genMultOneWord (operand *left,
4021 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4022 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4023 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4025 /* (if two literals, the value is computed before)
4026 * if one literal, literal on the right */
4027 if (AOP_TYPE(left) == AOP_LIT){
4033 /* size is checked already == 2 */
4034 // size = AOP_SIZE(result);
4036 if (AOP_TYPE(right) == AOP_LIT) {
4037 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4038 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4039 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4040 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4042 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4043 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4044 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4045 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4048 pic16_genMult16X16_16(left, right,result);
4051 /*-----------------------------------------------------------------*/
4052 /* genMultOneLong : 32 bit multiplication */
4053 /*-----------------------------------------------------------------*/
4054 static void genMultOneLong (operand *left,
4059 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4060 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4061 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4063 /* (if two literals, the value is computed before)
4064 * if one literal, literal on the right */
4065 if (AOP_TYPE(left) == AOP_LIT){
4071 /* size is checked already == 4 */
4072 // size = AOP_SIZE(result);
4074 if (AOP_TYPE(right) == AOP_LIT) {
4075 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4076 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4077 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4078 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4080 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4081 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4082 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4083 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4086 pic16_genMult32X32_32(left, right,result);
4091 /*-----------------------------------------------------------------*/
4092 /* genMult - generates code for multiplication */
4093 /*-----------------------------------------------------------------*/
4094 static void genMult (iCode *ic)
4096 operand *left = IC_LEFT(ic);
4097 operand *right = IC_RIGHT(ic);
4098 operand *result= IC_RESULT(ic);
4100 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4101 /* assign the amsops */
4102 pic16_aopOp (left,ic,FALSE);
4103 pic16_aopOp (right,ic,FALSE);
4104 pic16_aopOp (result,ic,TRUE);
4106 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4108 /* special cases first *
4110 if (AOP_TYPE(left) == AOP_CRY
4111 && AOP_TYPE(right)== AOP_CRY) {
4112 genMultbits(left,right,result);
4116 /* if both are of size == 1 */
4117 if(AOP_SIZE(left) == 1
4118 && AOP_SIZE(right) == 1) {
4119 genMultOneByte(left,right,result);
4123 /* if both are of size == 2 */
4124 if(AOP_SIZE(left) == 2
4125 && AOP_SIZE(right) == 2) {
4126 genMultOneWord(left, right, result);
4130 /* if both are of size == 4 */
4131 if(AOP_SIZE(left) == 4
4132 && AOP_SIZE(right) == 4) {
4133 genMultOneLong(left, right, result);
4137 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4140 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4141 /* should have been converted to function call */
4145 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4146 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4147 pic16_freeAsmop(result,NULL,ic,TRUE);
4150 /*-----------------------------------------------------------------*/
4151 /* genDivbits :- division of bits */
4152 /*-----------------------------------------------------------------*/
4153 static void genDivbits (operand *left,
4160 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4161 /* the result must be bit */
4162 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4163 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4167 pic16_emitcode("div","ab");
4168 pic16_emitcode("rrc","a");
4169 pic16_aopPut(AOP(result),"c",0);
4172 /*-----------------------------------------------------------------*/
4173 /* genDivOneByte : 8 bit division */
4174 /*-----------------------------------------------------------------*/
4175 static void genDivOneByte (operand *left,
4179 sym_link *opetype = operandType(result);
4184 /* result = divident / divisor
4185 * - divident may be a register or a literal,
4186 * - divisor may be a register or a literal,
4187 * so there are 3 cases (literal / literal is optimized
4188 * by the front-end) to handle.
4189 * In addition we must handle signed and unsigned, which
4190 * result in 6 final different cases -- VR */
4192 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4193 size = AOP_SIZE(result) - 1;
4195 /* signed or unsigned */
4196 if (SPEC_USIGN(opetype)) {
4197 pCodeOp *pct1, /* count */
4200 symbol *label1, *label2, *label3;;
4203 /* unsigned is easy */
4205 pct1 = pic16_popGetTempReg();
4206 pct2 = pic16_popGetTempReg();
4207 pct3 = pic16_popGetTempReg();
4209 label1 = newiTempLabel(NULL);
4210 label2 = newiTempLabel(NULL);
4211 label3 = newiTempLabel(NULL);
4213 /* the following algorithm is extracted from divuint.c */
4215 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4216 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4218 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4220 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4222 pic16_emitpLabel(label1->key);
4225 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4229 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4233 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4235 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4236 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4238 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4239 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4240 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4242 pic16_emitpLabel( label3->key );
4243 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4244 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4248 pic16_emitpLabel(label2->key);
4249 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4250 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4251 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4253 /* result is in wreg */
4254 if(AOP_TYPE(result) != AOP_ACC)
4255 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4257 pic16_popReleaseTempReg( pct3 );
4258 pic16_popReleaseTempReg( pct2 );
4259 pic16_popReleaseTempReg( pct1 );
4264 /* signed is a little bit more difficult */
4266 /* save the signs of the operands */
4267 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4269 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4270 pic16_emitcode("push","acc"); /* save it on the stack */
4272 /* now sign adjust for both left & right */
4273 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4275 lbl = newiTempLabel(NULL);
4276 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4277 pic16_emitcode("cpl","a");
4278 pic16_emitcode("inc","a");
4279 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4280 pic16_emitcode("mov","b,a");
4282 /* sign adjust left side */
4283 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4286 lbl = newiTempLabel(NULL);
4287 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4288 pic16_emitcode("cpl","a");
4289 pic16_emitcode("inc","a");
4290 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4292 /* now the division */
4293 pic16_emitcode("div","ab");
4294 /* we are interested in the lower order
4296 pic16_emitcode("mov","b,a");
4297 lbl = newiTempLabel(NULL);
4298 pic16_emitcode("pop","acc");
4299 /* if there was an over flow we don't
4300 adjust the sign of the result */
4301 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4302 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4304 pic16_emitcode("clr","a");
4305 pic16_emitcode("subb","a,b");
4306 pic16_emitcode("mov","b,a");
4307 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4309 /* now we are done */
4310 pic16_aopPut(AOP(result),"b",0);
4312 pic16_emitcode("mov","c,b.7");
4313 pic16_emitcode("subb","a,acc");
4316 pic16_aopPut(AOP(result),"a",offset++);
4320 /*-----------------------------------------------------------------*/
4321 /* genDiv - generates code for division */
4322 /*-----------------------------------------------------------------*/
4323 static void genDiv (iCode *ic)
4325 operand *left = IC_LEFT(ic);
4326 operand *right = IC_RIGHT(ic);
4327 operand *result= IC_RESULT(ic);
4330 /* Division is a very lengthy algorithm, so it is better
4331 * to call support routines than inlining algorithm.
4332 * Division functions written here just in case someone
4333 * wants to inline and not use the support libraries -- VR */
4335 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4336 /* assign the amsops */
4337 pic16_aopOp (left,ic,FALSE);
4338 pic16_aopOp (right,ic,FALSE);
4339 pic16_aopOp (result,ic,TRUE);
4341 /* special cases first */
4343 if (AOP_TYPE(left) == AOP_CRY &&
4344 AOP_TYPE(right)== AOP_CRY) {
4345 genDivbits(left,right,result);
4349 /* if both are of size == 1 */
4350 if (AOP_SIZE(left) == 1 &&
4351 AOP_SIZE(right) == 1 ) {
4352 genDivOneByte(left,right,result);
4356 /* should have been converted to function call */
4359 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4360 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4361 pic16_freeAsmop(result,NULL,ic,TRUE);
4364 /*-----------------------------------------------------------------*/
4365 /* genModbits :- modulus of bits */
4366 /*-----------------------------------------------------------------*/
4367 static void genModbits (operand *left,
4374 /* the result must be bit */
4375 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4376 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4380 pic16_emitcode("div","ab");
4381 pic16_emitcode("mov","a,b");
4382 pic16_emitcode("rrc","a");
4383 pic16_aopPut(AOP(result),"c",0);
4386 /*-----------------------------------------------------------------*/
4387 /* genModOneByte : 8 bit modulus */
4388 /*-----------------------------------------------------------------*/
4389 static void genModOneByte (operand *left,
4393 sym_link *opetype = operandType(result);
4397 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4398 /* signed or unsigned */
4399 if (SPEC_USIGN(opetype)) {
4400 /* unsigned is easy */
4401 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4402 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4404 pic16_emitcode("div","ab");
4405 pic16_aopPut(AOP(result),"b",0);
4409 /* signed is a little bit more difficult */
4411 /* save the signs of the operands */
4412 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4415 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4416 pic16_emitcode("push","acc"); /* save it on the stack */
4418 /* now sign adjust for both left & right */
4419 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4422 lbl = newiTempLabel(NULL);
4423 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4424 pic16_emitcode("cpl","a");
4425 pic16_emitcode("inc","a");
4426 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4427 pic16_emitcode("mov","b,a");
4429 /* sign adjust left side */
4430 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4433 lbl = newiTempLabel(NULL);
4434 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4435 pic16_emitcode("cpl","a");
4436 pic16_emitcode("inc","a");
4437 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4439 /* now the multiplication */
4440 pic16_emitcode("div","ab");
4441 /* we are interested in the lower order
4443 lbl = newiTempLabel(NULL);
4444 pic16_emitcode("pop","acc");
4445 /* if there was an over flow we don't
4446 adjust the sign of the result */
4447 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4448 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4450 pic16_emitcode("clr","a");
4451 pic16_emitcode("subb","a,b");
4452 pic16_emitcode("mov","b,a");
4453 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4455 /* now we are done */
4456 pic16_aopPut(AOP(result),"b",0);
4460 /*-----------------------------------------------------------------*/
4461 /* genMod - generates code for division */
4462 /*-----------------------------------------------------------------*/
4463 static void genMod (iCode *ic)
4465 operand *left = IC_LEFT(ic);
4466 operand *right = IC_RIGHT(ic);
4467 operand *result= IC_RESULT(ic);
4469 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4470 /* assign the amsops */
4471 pic16_aopOp (left,ic,FALSE);
4472 pic16_aopOp (right,ic,FALSE);
4473 pic16_aopOp (result,ic,TRUE);
4475 /* special cases first */
4477 if (AOP_TYPE(left) == AOP_CRY &&
4478 AOP_TYPE(right)== AOP_CRY) {
4479 genModbits(left,right,result);
4483 /* if both are of size == 1 */
4484 if (AOP_SIZE(left) == 1 &&
4485 AOP_SIZE(right) == 1 ) {
4486 genModOneByte(left,right,result);
4490 /* should have been converted to function call */
4494 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4495 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4496 pic16_freeAsmop(result,NULL,ic,TRUE);
4499 /*-----------------------------------------------------------------*/
4500 /* genIfxJump :- will create a jump depending on the ifx */
4501 /*-----------------------------------------------------------------*/
4503 note: May need to add parameter to indicate when a variable is in bit space.
4505 static void genIfxJump (iCode *ic, char *jval)
4508 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4509 /* if true label then we jump if condition
4511 if ( IC_TRUE(ic) ) {
4513 if(strcmp(jval,"a") == 0)
4515 else if (strcmp(jval,"c") == 0)
4518 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4519 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4522 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4523 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4527 /* false label is present */
4528 if(strcmp(jval,"a") == 0)
4530 else if (strcmp(jval,"c") == 0)
4533 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4534 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4537 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4538 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4543 /* mark the icode as generated */
4550 /*-----------------------------------------------------------------*/
4552 /*-----------------------------------------------------------------*/
4553 static void genSkip(iCode *ifx,int status_bit)
4555 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4559 if ( IC_TRUE(ifx) ) {
4560 switch(status_bit) {
4575 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4576 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4580 switch(status_bit) {
4594 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4595 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4602 /*-----------------------------------------------------------------*/
4604 /*-----------------------------------------------------------------*/
4605 static void genSkipc(resolvedIfx *rifx)
4607 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4617 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4618 rifx->generated = 1;
4621 /*-----------------------------------------------------------------*/
4623 /*-----------------------------------------------------------------*/
4624 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4626 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4631 if( (rifx->condition ^ invert_condition) & 1)
4636 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4637 rifx->generated = 1;
4641 /*-----------------------------------------------------------------*/
4643 /*-----------------------------------------------------------------*/
4644 static void genSkipz(iCode *ifx, int condition)
4655 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4657 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4660 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4662 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4667 /*-----------------------------------------------------------------*/
4669 /*-----------------------------------------------------------------*/
4670 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4676 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4678 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4681 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4682 rifx->generated = 1;
4686 /*-----------------------------------------------------------------*/
4687 /* genChkZeroes :- greater or less than comparison */
4688 /* For each byte in a literal that is zero, inclusive or the */
4689 /* the corresponding byte in the operand with W */
4690 /* returns true if any of the bytes are zero */
4691 /*-----------------------------------------------------------------*/
4692 static int genChkZeroes(operand *op, int lit, int size)
4699 i = (lit >> (size*8)) & 0xff;
4703 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4705 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4714 /*-----------------------------------------------------------------*/
4715 /* genCmp :- greater or less than comparison */
4716 /*-----------------------------------------------------------------*/
4717 static void genCmp (operand *left,operand *right,
4718 operand *result, iCode *ifx, int sign)
4720 int size; //, offset = 0 ;
4721 unsigned long lit = 0L,i = 0;
4722 resolvedIfx rFalseIfx;
4723 // resolvedIfx rTrueIfx;
4725 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4728 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4729 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4733 resolveIfx(&rFalseIfx,ifx);
4734 truelbl = newiTempLabel(NULL);
4735 size = max(AOP_SIZE(left),AOP_SIZE(right));
4737 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4741 /* if literal is on the right then swap with left */
4742 if ((AOP_TYPE(right) == AOP_LIT)) {
4743 operand *tmp = right ;
4744 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4745 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4748 lit = (lit - 1) & mask;
4751 rFalseIfx.condition ^= 1;
4754 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4755 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4759 //if(IC_TRUE(ifx) == NULL)
4760 /* if left & right are bit variables */
4761 if (AOP_TYPE(left) == AOP_CRY &&
4762 AOP_TYPE(right) == AOP_CRY ) {
4763 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4764 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4766 /* subtract right from left if at the
4767 end the carry flag is set then we know that
4768 left is greater than right */
4770 symbol *lbl = newiTempLabel(NULL);
4773 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4774 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4778 if(AOP_TYPE(right) == AOP_LIT) {
4780 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4782 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4789 genSkipCond(&rFalseIfx,left,size-1,7);
4791 /* no need to compare to 0...*/
4792 /* NOTE: this is a de-generate compare that most certainly
4793 * creates some dead code. */
4794 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4796 if(ifx) ifx->generated = 1;
4803 //i = (lit >> (size*8)) & 0xff;
4804 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4806 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4808 i = ((0-lit) & 0xff);
4811 /* lit is 0x7f, all signed chars are less than
4812 * this except for 0x7f itself */
4813 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4814 genSkipz2(&rFalseIfx,0);
4816 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4817 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4818 genSkipc(&rFalseIfx);
4823 genSkipz2(&rFalseIfx,1);
4825 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4826 genSkipc(&rFalseIfx);
4830 if(ifx) ifx->generated = 1;
4834 /* chars are out of the way. now do ints and longs */
4837 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4844 genSkipCond(&rFalseIfx,left,size,7);
4845 if(ifx) ifx->generated = 1;
4850 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4852 //rFalseIfx.condition ^= 1;
4853 //genSkipCond(&rFalseIfx,left,size,7);
4854 //rFalseIfx.condition ^= 1;
4856 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4857 if(rFalseIfx.condition)
4858 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4860 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4862 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4863 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4864 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4867 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4869 if(rFalseIfx.condition) {
4871 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4877 genSkipc(&rFalseIfx);
4878 pic16_emitpLabel(truelbl->key);
4879 if(ifx) ifx->generated = 1;
4886 if( (lit & 0xff) == 0) {
4887 /* lower byte is zero */
4888 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4889 i = ((lit >> 8) & 0xff) ^0x80;
4890 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4891 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4892 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4893 genSkipc(&rFalseIfx);
4896 if(ifx) ifx->generated = 1;
4901 /* Special cases for signed longs */
4902 if( (lit & 0xffffff) == 0) {
4903 /* lower byte is zero */
4904 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4905 i = ((lit >> 8*3) & 0xff) ^0x80;
4906 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4907 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4908 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4909 genSkipc(&rFalseIfx);
4912 if(ifx) ifx->generated = 1;
4920 if(lit & (0x80 << (size*8))) {
4921 /* lit is negative */
4922 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4924 //genSkipCond(&rFalseIfx,left,size,7);
4926 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4928 if(rFalseIfx.condition)
4929 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4931 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4935 /* lit is positive */
4936 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4937 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4938 if(rFalseIfx.condition)
4939 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4941 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4946 This works, but is only good for ints.
4947 It also requires a "known zero" register.
4948 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4949 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4950 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
4951 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4952 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4953 genSkipc(&rFalseIfx);
4955 pic16_emitpLabel(truelbl->key);
4956 if(ifx) ifx->generated = 1;
4960 /* There are no more special cases, so perform a general compare */
4962 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4963 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4967 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4969 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4971 //rFalseIfx.condition ^= 1;
4972 genSkipc(&rFalseIfx);
4974 pic16_emitpLabel(truelbl->key);
4976 if(ifx) ifx->generated = 1;
4983 /* sign is out of the way. So now do an unsigned compare */
4984 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4987 /* General case - compare to an unsigned literal on the right.*/
4989 i = (lit >> (size*8)) & 0xff;
4990 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4991 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4993 i = (lit >> (size*8)) & 0xff;
4996 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4998 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5000 /* this byte of the lit is zero,
5001 *if it's not the last then OR in the variable */
5003 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5008 pic16_emitpLabel(lbl->key);
5009 // pic16_emitpLabel(truelbl->key);
5010 //if(emitFinalCheck)
5011 genSkipc(&rFalseIfx);
5013 pic16_emitpLabel(truelbl->key);
5015 if(ifx) ifx->generated = 1;
5022 if(AOP_TYPE(left) == AOP_LIT) {
5023 //symbol *lbl = newiTempLabel(NULL);
5025 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5028 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5031 if((lit == 0) && (sign == 0)){
5034 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5036 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5038 genSkipz2(&rFalseIfx,0);
5039 if(ifx) ifx->generated = 1;
5046 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5047 /* degenerate compare can never be true */
5048 if(rFalseIfx.condition == 0)
5049 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5051 if(ifx) ifx->generated = 1;
5056 /* signed comparisons to a literal byte */
5058 int lp1 = (lit+1) & 0xff;
5060 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5063 rFalseIfx.condition ^= 1;
5064 genSkipCond(&rFalseIfx,right,0,7);
5067 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5068 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5069 genSkipz2(&rFalseIfx,1);
5072 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5073 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5074 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5075 rFalseIfx.condition ^= 1;
5076 genSkipc(&rFalseIfx);
5080 /* unsigned comparisons to a literal byte */
5082 switch(lit & 0xff ) {
5084 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5085 genSkipz2(&rFalseIfx,0);
5088 rFalseIfx.condition ^= 1;
5089 genSkipCond(&rFalseIfx,right,0,7);
5093 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5094 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5095 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5096 rFalseIfx.condition ^= 1;
5097 if (AOP_TYPE(result) == AOP_CRY)
5098 genSkipc(&rFalseIfx);
5100 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5101 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5107 if(ifx) ifx->generated = 1;
5108 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5114 /* Size is greater than 1 */
5122 /* this means lit = 0xffffffff, or -1 */
5125 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5126 rFalseIfx.condition ^= 1;
5127 genSkipCond(&rFalseIfx,right,size,7);
5128 if(ifx) ifx->generated = 1;
5135 if(rFalseIfx.condition) {
5136 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5137 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5140 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5142 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5146 if(rFalseIfx.condition) {
5147 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5148 pic16_emitpLabel(truelbl->key);
5150 rFalseIfx.condition ^= 1;
5151 genSkipCond(&rFalseIfx,right,s,7);
5154 if(ifx) ifx->generated = 1;
5158 if((size == 1) && (0 == (lp1&0xff))) {
5159 /* lower byte of signed word is zero */
5160 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5161 i = ((lp1 >> 8) & 0xff) ^0x80;
5162 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5163 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5164 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5165 rFalseIfx.condition ^= 1;
5166 genSkipc(&rFalseIfx);
5169 if(ifx) ifx->generated = 1;
5173 if(lit & (0x80 << (size*8))) {
5174 /* Lit is less than zero */
5175 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5176 //rFalseIfx.condition ^= 1;
5177 //genSkipCond(&rFalseIfx,left,size,7);
5178 //rFalseIfx.condition ^= 1;
5179 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5180 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5182 if(rFalseIfx.condition)
5183 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5185 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5189 /* Lit is greater than or equal to zero */
5190 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5191 //rFalseIfx.condition ^= 1;
5192 //genSkipCond(&rFalseIfx,right,size,7);
5193 //rFalseIfx.condition ^= 1;
5195 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5196 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5198 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5199 if(rFalseIfx.condition)
5200 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5202 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5207 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5208 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5212 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5214 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5216 rFalseIfx.condition ^= 1;
5217 //rFalseIfx.condition = 1;
5218 genSkipc(&rFalseIfx);
5220 pic16_emitpLabel(truelbl->key);
5222 if(ifx) ifx->generated = 1;
5227 /* compare word or long to an unsigned literal on the right.*/
5232 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5235 break; /* handled above */
5238 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5240 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5241 genSkipz2(&rFalseIfx,0);
5245 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5247 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5250 if(rFalseIfx.condition)
5251 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5253 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5256 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5257 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5259 rFalseIfx.condition ^= 1;
5260 genSkipc(&rFalseIfx);
5263 pic16_emitpLabel(truelbl->key);
5265 if(ifx) ifx->generated = 1;
5271 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5272 i = (lit >> (size*8)) & 0xff;
5274 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5275 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5278 i = (lit >> (size*8)) & 0xff;
5281 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5283 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5285 /* this byte of the lit is zero,
5286 * if it's not the last then OR in the variable */
5288 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5293 pic16_emitpLabel(lbl->key);
5295 rFalseIfx.condition ^= 1;
5297 genSkipc(&rFalseIfx);
5301 pic16_emitpLabel(truelbl->key);
5302 if(ifx) ifx->generated = 1;
5306 /* Compare two variables */
5308 DEBUGpic16_emitcode(";sign","%d",sign);
5312 /* Sigh. thus sucks... */
5316 pctemp = pic16_popGetTempReg();
5317 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5318 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5319 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5320 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5321 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5322 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5323 pic16_popReleaseTempReg(pctemp);
5325 /* Signed char comparison */
5326 /* Special thanks to Nikolai Golovchenko for this snippet */
5327 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5328 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5329 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5330 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5331 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5332 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5334 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5335 genSkipc(&rFalseIfx);
5337 if(ifx) ifx->generated = 1;
5343 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5344 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5348 /* The rest of the bytes of a multi-byte compare */
5352 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5355 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5356 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5361 pic16_emitpLabel(lbl->key);
5363 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5364 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5365 (AOP_TYPE(result) == AOP_REG)) {
5366 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5367 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5369 genSkipc(&rFalseIfx);
5371 //genSkipc(&rFalseIfx);
5372 if(ifx) ifx->generated = 1;
5379 if ((AOP_TYPE(result) != AOP_CRY)
5380 && AOP_SIZE(result)) {
5381 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5383 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5385 pic16_outBitC(result);
5387 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5388 /* if the result is used in the next
5389 ifx conditional branch then generate
5390 code a little differently */
5392 genIfxJump (ifx,"c");
5394 pic16_outBitC(result);
5395 /* leave the result in acc */
5400 /*-----------------------------------------------------------------*/
5401 /* genCmpGt :- greater than comparison */
5402 /*-----------------------------------------------------------------*/
5403 static void genCmpGt (iCode *ic, iCode *ifx)
5405 operand *left, *right, *result;
5406 sym_link *letype , *retype;
5409 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5411 right= IC_RIGHT(ic);
5412 result = IC_RESULT(ic);
5414 letype = getSpec(operandType(left));
5415 retype =getSpec(operandType(right));
5416 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5417 /* assign the amsops */
5418 pic16_aopOp (left,ic,FALSE);
5419 pic16_aopOp (right,ic,FALSE);
5420 pic16_aopOp (result,ic,TRUE);
5422 genCmp(right, left, result, ifx, sign);
5424 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5425 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5426 pic16_freeAsmop(result,NULL,ic,TRUE);
5429 /*-----------------------------------------------------------------*/
5430 /* genCmpLt - less than comparisons */
5431 /*-----------------------------------------------------------------*/
5432 static void genCmpLt (iCode *ic, iCode *ifx)
5434 operand *left, *right, *result;
5435 sym_link *letype , *retype;
5438 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5440 right= IC_RIGHT(ic);
5441 result = IC_RESULT(ic);
5443 letype = getSpec(operandType(left));
5444 retype =getSpec(operandType(right));
5445 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5447 /* assign the amsops */
5448 pic16_aopOp (left,ic,FALSE);
5449 pic16_aopOp (right,ic,FALSE);
5450 pic16_aopOp (result,ic,TRUE);
5452 genCmp(left, right, result, ifx, sign);
5454 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5455 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5456 pic16_freeAsmop(result,NULL,ic,TRUE);
5461 // FIXME reenable literal optimisation when the pic16 port is stable
5463 /*-----------------------------------------------------------------*/
5464 /* genc16bit2lit - compare a 16 bit value to a literal */
5465 /*-----------------------------------------------------------------*/
5466 static void genc16bit2lit(operand *op, int lit, int offset)
5470 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
5471 if( (lit&0xff) == 0)
5476 switch( BYTEofLONG(lit,i)) {
5478 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5481 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5484 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5487 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5488 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5493 switch( BYTEofLONG(lit,i)) {
5495 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5499 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5503 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5506 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5508 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5517 /*-----------------------------------------------------------------*/
5518 /* gencjneshort - compare and jump if not equal */
5519 /*-----------------------------------------------------------------*/
5520 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5522 int size = max(AOP_SIZE(left),AOP_SIZE(right));
5524 int res_offset = 0; /* the result may be a different size then left or right */
5525 int res_size = AOP_SIZE(result);
5527 symbol *lbl, *lbl_done;
5529 unsigned long lit = 0L;
5530 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5532 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5533 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5535 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
5536 resolveIfx(&rIfx,ifx);
5537 lbl = newiTempLabel(NULL);
5538 lbl_done = newiTempLabel(NULL);
5541 /* if the left side is a literal or
5542 if the right is in a pointer register and left
5544 if ((AOP_TYPE(left) == AOP_LIT) ||
5545 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5550 if(AOP_TYPE(right) == AOP_LIT)
5551 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5553 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5554 preserve_result = 1;
5556 if(result && !preserve_result)
5559 for(i = 0; i < AOP_SIZE(result); i++)
5560 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5564 /* if the right side is a literal then anything goes */
5565 if (AOP_TYPE(right) == AOP_LIT &&
5566 AOP_TYPE(left) != AOP_DIR ) {
5569 genc16bit2lit(left, lit, 0);
5571 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5574 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5577 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5578 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5580 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5584 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5586 if(res_offset < res_size-1)
5594 /* if the right side is in a register or in direct space or
5595 if the left is a pointer register & right is not */
5596 else if (AOP_TYPE(right) == AOP_REG ||
5597 AOP_TYPE(right) == AOP_DIR ||
5598 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5599 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5600 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5601 int lbl_key = lbl->key;
5604 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5605 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5607 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5608 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5609 __FUNCTION__,__LINE__);
5613 /* switch(size) { */
5615 /* genc16bit2lit(left, lit, 0); */
5617 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5622 if((AOP_TYPE(left) == AOP_DIR) &&
5623 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5625 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5626 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5628 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5630 switch (lit & 0xff) {
5632 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5635 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5636 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5637 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5641 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5642 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5643 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5644 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5648 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5649 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5654 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5657 if(AOP_TYPE(result) == AOP_CRY) {
5658 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5663 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5665 /* fix me. probably need to check result size too */
5666 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5671 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5672 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5679 if(res_offset < res_size-1)
5684 } else if(AOP_TYPE(right) == AOP_REG &&
5685 AOP_TYPE(left) != AOP_DIR){
5688 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5689 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5690 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5695 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5697 if(res_offset < res_size-1)
5702 /* right is a pointer reg need both a & b */
5704 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5706 pic16_emitcode("mov","b,%s",l);
5707 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5708 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5713 if(result && preserve_result)
5716 for(i = 0; i < AOP_SIZE(result); i++)
5717 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5720 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5722 if(result && preserve_result)
5723 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5726 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5728 pic16_emitpLabel(lbl->key);
5730 if(result && preserve_result)
5733 for(i = 0; i < AOP_SIZE(result); i++)
5734 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5736 pic16_emitpLabel(lbl_done->key);
5739 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5747 /*-----------------------------------------------------------------*/
5748 /* gencjne - compare and jump if not equal */
5749 /*-----------------------------------------------------------------*/
5750 static void gencjne(operand *left, operand *right, iCode *ifx)
5752 symbol *tlbl = newiTempLabel(NULL);
5754 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5755 gencjneshort(left, right, lbl);
5757 pic16_emitcode("mov","a,%s",one);
5758 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5759 pic16_emitcode("","%05d_DS_:",lbl->key+100);
5760 pic16_emitcode("clr","a");
5761 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5763 pic16_emitpLabel(lbl->key);
5764 pic16_emitpLabel(tlbl->key);
5770 /*-----------------------------------------------------------------*/
5771 /* is_LitOp - check if operand has to be treated as literal */
5772 /*-----------------------------------------------------------------*/
5773 static bool is_LitOp(operand *op)
5775 return (AOP_TYPE(op) == AOP_LIT)
5776 || ( (AOP_TYPE(op) == AOP_PCODE)
5777 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5778 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));
5781 /*-----------------------------------------------------------------*/
5782 /* is_LitAOp - check if operand has to be treated as literal */
5783 /*-----------------------------------------------------------------*/
5784 static bool is_LitAOp(asmop *aop)
5786 return (aop->type == AOP_LIT)
5787 || ( (aop->type == AOP_PCODE)
5788 && ( (aop->aopu.pcop->type == PO_LITERAL)
5789 || (aop->aopu.pcop->type == PO_IMMEDIATE) ));
5794 /*-----------------------------------------------------------------*/
5795 /* genCmpEq - generates code for equal to */
5796 /*-----------------------------------------------------------------*/
5797 static void genCmpEq (iCode *ic, iCode *ifx)
5799 operand *left, *right, *result;
5800 symbol *falselbl = newiTempLabel(NULL);
5801 symbol *donelbl = newiTempLabel(NULL);
5803 int preserve_result = 0;
5804 int generate_result = 0;
5807 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5808 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5809 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5811 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5812 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5814 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5816 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5817 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5821 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5823 operand *tmp = right ;
5828 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5829 preserve_result = 1;
5831 if(result && AOP_SIZE(result))
5832 generate_result = 1;
5834 if(generate_result && !preserve_result)
5836 for(i = 0; i < AOP_SIZE(result); i++)
5837 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5840 for(i=0; i < AOP_SIZE(left); i++)
5842 if(AOP_TYPE(left) != AOP_ACC)
5845 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5847 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5850 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
5852 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
5854 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5859 if(generate_result && preserve_result)
5861 for(i = 0; i < AOP_SIZE(result); i++)
5862 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5866 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5868 if(generate_result && preserve_result)
5869 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5871 if(ifx && IC_TRUE(ifx))
5872 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5874 if(ifx && IC_FALSE(ifx))
5875 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5877 pic16_emitpLabel(falselbl->key);
5881 if(ifx && IC_FALSE(ifx))
5882 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5884 if(generate_result && preserve_result)
5886 for(i = 0; i < AOP_SIZE(result); i++)
5887 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5890 pic16_emitpLabel(donelbl->key);
5896 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5897 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5898 pic16_freeAsmop(result,NULL,ic,TRUE);
5904 // old version kept for reference
5906 /*-----------------------------------------------------------------*/
5907 /* genCmpEq - generates code for equal to */
5908 /*-----------------------------------------------------------------*/
5909 static void genCmpEq (iCode *ic, iCode *ifx)
5911 operand *left, *right, *result;
5912 unsigned long lit = 0L;
5914 symbol *falselbl = newiTempLabel(NULL);
5917 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5920 DEBUGpic16_emitcode ("; ifx is non-null","");
5922 DEBUGpic16_emitcode ("; ifx is null","");
5924 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5925 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5926 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5928 size = max(AOP_SIZE(left),AOP_SIZE(right));
5930 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5932 /* if literal, literal on the right or
5933 if the right is in a pointer register and left
5935 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
5936 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5937 operand *tmp = right ;
5943 if(ifx && !AOP_SIZE(result)){
5945 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
5946 /* if they are both bit variables */
5947 if (AOP_TYPE(left) == AOP_CRY &&
5948 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5949 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
5950 if(AOP_TYPE(right) == AOP_LIT){
5951 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5953 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5954 pic16_emitcode("cpl","c");
5955 } else if(lit == 1L) {
5956 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5958 pic16_emitcode("clr","c");
5960 /* AOP_TYPE(right) == AOP_CRY */
5962 symbol *lbl = newiTempLabel(NULL);
5963 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5964 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5965 pic16_emitcode("cpl","c");
5966 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5968 /* if true label then we jump if condition
5970 tlbl = newiTempLabel(NULL);
5971 if ( IC_TRUE(ifx) ) {
5972 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5973 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5975 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5976 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5978 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5981 /* left and right are both bit variables, result is carry */
5984 resolveIfx(&rIfx,ifx);
5986 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5987 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5988 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5989 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5994 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
5996 /* They're not both bit variables. Is the right a literal? */
5997 if(AOP_TYPE(right) == AOP_LIT) {
5998 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6003 switch(lit & 0xff) {
6005 if ( IC_TRUE(ifx) ) {
6006 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6008 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6010 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6011 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6015 if ( IC_TRUE(ifx) ) {
6016 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6018 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6020 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6021 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6025 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6027 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6032 /* end of size == 1 */
6036 genc16bit2lit(left,lit,offset);
6039 /* end of size == 2 */
6044 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6045 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6046 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6047 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6050 /* search for patterns that can be optimized */
6052 genc16bit2lit(left,lit,0);
6056 emitSKPZ; // if hi word unequal
6058 emitSKPNZ; // if hi word equal
6060 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6061 genc16bit2lit(left,lit,2);
6064 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6065 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6069 pic16_emitpLabel(falselbl->key);
6078 } else if(AOP_TYPE(right) == AOP_CRY ) {
6079 /* we know the left is not a bit, but that the right is */
6080 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6081 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6082 pic16_popGet(AOP(right),offset));
6083 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6085 /* if the two are equal, then W will be 0 and the Z bit is set
6086 * we could test Z now, or go ahead and check the high order bytes if
6087 * the variable we're comparing is larger than a byte. */
6090 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6092 if ( IC_TRUE(ifx) ) {
6094 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6095 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6098 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6099 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6103 /* They're both variables that are larger than bits */
6106 tlbl = newiTempLabel(NULL);
6109 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6110 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6112 if ( IC_TRUE(ifx) ) {
6116 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6118 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6119 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6123 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6126 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6127 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6132 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6134 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6135 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6139 if(s>1 && IC_TRUE(ifx)) {
6140 pic16_emitpLabel(tlbl->key);
6141 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6145 /* mark the icode as generated */
6150 /* if they are both bit variables */
6151 if (AOP_TYPE(left) == AOP_CRY &&
6152 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6153 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
6154 if(AOP_TYPE(right) == AOP_LIT){
6155 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6157 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6158 pic16_emitcode("cpl","c");
6159 } else if(lit == 1L) {
6160 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6162 pic16_emitcode("clr","c");
6164 /* AOP_TYPE(right) == AOP_CRY */
6166 symbol *lbl = newiTempLabel(NULL);
6167 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6168 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6169 pic16_emitcode("cpl","c");
6170 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6173 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6174 pic16_outBitC(result);
6178 genIfxJump (ifx,"c");
6181 /* if the result is used in an arithmetic operation
6182 then put the result in place */
6183 pic16_outBitC(result);
6186 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
6187 gencjne(left,right,result,ifx);
6190 gencjne(left,right,newiTempLabel(NULL));
6192 if(IC_TRUE(ifx)->key)
6193 gencjne(left,right,IC_TRUE(ifx)->key);
6195 gencjne(left,right,IC_FALSE(ifx)->key);
6199 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6200 pic16_aopPut(AOP(result),"a",0);
6205 genIfxJump (ifx,"a");
6209 /* if the result is used in an arithmetic operation
6210 then put the result in place */
6212 if (AOP_TYPE(result) != AOP_CRY)
6213 pic16_outAcc(result);
6215 /* leave the result in acc */
6219 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6220 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6221 pic16_freeAsmop(result,NULL,ic,TRUE);
6225 /*-----------------------------------------------------------------*/
6226 /* ifxForOp - returns the icode containing the ifx for operand */
6227 /*-----------------------------------------------------------------*/
6228 static iCode *ifxForOp ( operand *op, iCode *ic )
6230 /* if true symbol then needs to be assigned */
6231 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6232 if (IS_TRUE_SYMOP(op))
6235 /* if this has register type condition and
6236 the next instruction is ifx with the same operand
6237 and live to of the operand is upto the ifx only then */
6239 && ic->next->op == IFX
6240 && IC_COND(ic->next)->key == op->key
6241 && OP_SYMBOL(op)->liveTo <= ic->next->seq
6243 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6248 ic->next->op == IFX &&
6249 IC_COND(ic->next)->key == op->key) {
6250 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6254 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6256 ic->next->op == IFX)
6257 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6260 ic->next->op == IFX &&
6261 IC_COND(ic->next)->key == op->key) {
6262 DEBUGpic16_emitcode ("; "," key is okay");
6263 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6264 OP_SYMBOL(op)->liveTo,
6269 /* the code below is completely untested
6270 * it just allows ulong2fs.c compile -- VR */
6273 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6274 __FILE__, __FUNCTION__, __LINE__);
6276 /* if this has register type condition and
6277 the next instruction is ifx with the same operand
6278 and live to of the operand is upto the ifx only then */
6280 ic->next->op == IFX &&
6281 IC_COND(ic->next)->key == op->key &&
6282 OP_SYMBOL(op)->liveTo <= ic->next->seq )
6286 ic->next->op == IFX &&
6287 IC_COND(ic->next)->key == op->key) {
6288 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6292 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6293 __FILE__, __FUNCTION__, __LINE__);
6295 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
6300 /*-----------------------------------------------------------------*/
6301 /* genAndOp - for && operation */
6302 /*-----------------------------------------------------------------*/
6303 static void genAndOp (iCode *ic)
6305 operand *left,*right, *result;
6308 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6309 /* note here that && operations that are in an
6310 if statement are taken away by backPatchLabels
6311 only those used in arthmetic operations remain */
6312 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6313 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6314 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6316 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6318 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6319 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6320 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6322 /* if both are bit variables */
6323 /* if (AOP_TYPE(left) == AOP_CRY && */
6324 /* AOP_TYPE(right) == AOP_CRY ) { */
6325 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6326 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6327 /* pic16_outBitC(result); */
6329 /* tlbl = newiTempLabel(NULL); */
6330 /* pic16_toBoolean(left); */
6331 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6332 /* pic16_toBoolean(right); */
6333 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6334 /* pic16_outBitAcc(result); */
6337 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6338 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6339 pic16_freeAsmop(result,NULL,ic,TRUE);
6343 /*-----------------------------------------------------------------*/
6344 /* genOrOp - for || operation */
6345 /*-----------------------------------------------------------------*/
6348 modified this code, but it doesn't appear to ever get called
6351 static void genOrOp (iCode *ic)
6353 operand *left,*right, *result;
6356 /* note here that || operations that are in an
6357 if statement are taken away by backPatchLabels
6358 only those used in arthmetic operations remain */
6359 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6360 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6361 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6362 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6364 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6366 /* if both are bit variables */
6367 if (AOP_TYPE(left) == AOP_CRY &&
6368 AOP_TYPE(right) == AOP_CRY ) {
6369 pic16_emitcode("clrc","");
6370 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6371 AOP(left)->aopu.aop_dir,
6372 AOP(left)->aopu.aop_dir);
6373 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6374 AOP(right)->aopu.aop_dir,
6375 AOP(right)->aopu.aop_dir);
6376 pic16_emitcode("setc","");
6379 tlbl = newiTempLabel(NULL);
6380 pic16_toBoolean(left);
6382 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6383 pic16_toBoolean(right);
6384 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6386 pic16_outBitAcc(result);
6389 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6390 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6391 pic16_freeAsmop(result,NULL,ic,TRUE);
6394 /*-----------------------------------------------------------------*/
6395 /* isLiteralBit - test if lit == 2^n */
6396 /*-----------------------------------------------------------------*/
6397 static int isLiteralBit(unsigned long lit)
6399 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6400 0x100L,0x200L,0x400L,0x800L,
6401 0x1000L,0x2000L,0x4000L,0x8000L,
6402 0x10000L,0x20000L,0x40000L,0x80000L,
6403 0x100000L,0x200000L,0x400000L,0x800000L,
6404 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6405 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6408 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6409 for(idx = 0; idx < 32; idx++)
6415 /*-----------------------------------------------------------------*/
6416 /* continueIfTrue - */
6417 /*-----------------------------------------------------------------*/
6418 static void continueIfTrue (iCode *ic)
6420 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6422 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6426 /*-----------------------------------------------------------------*/
6428 /*-----------------------------------------------------------------*/
6429 static void jumpIfTrue (iCode *ic)
6431 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6433 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6437 /*-----------------------------------------------------------------*/
6438 /* jmpTrueOrFalse - */
6439 /*-----------------------------------------------------------------*/
6440 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6442 // ugly but optimized by peephole
6443 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6445 symbol *nlbl = newiTempLabel(NULL);
6446 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
6447 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6448 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6449 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6452 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6453 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6458 /*-----------------------------------------------------------------*/
6459 /* genAnd - code for and */
6460 /*-----------------------------------------------------------------*/
6461 static void genAnd (iCode *ic, iCode *ifx)
6463 operand *left, *right, *result;
6465 unsigned long lit = 0L;
6470 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6471 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6472 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6473 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6475 resolveIfx(&rIfx,ifx);
6477 /* if left is a literal & right is not then exchange them */
6478 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6479 AOP_NEEDSACC(left)) {
6480 operand *tmp = right ;
6485 /* if result = right then exchange them */
6486 if(pic16_sameRegs(AOP(result),AOP(right))){
6487 operand *tmp = right ;
6492 /* if right is bit then exchange them */
6493 if (AOP_TYPE(right) == AOP_CRY &&
6494 AOP_TYPE(left) != AOP_CRY){
6495 operand *tmp = right ;
6499 if(AOP_TYPE(right) == AOP_LIT)
6500 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6502 size = AOP_SIZE(result);
6504 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6507 // result = bit & yy;
6508 if (AOP_TYPE(left) == AOP_CRY){
6509 // c = bit & literal;
6510 if(AOP_TYPE(right) == AOP_LIT){
6512 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6515 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6518 if(size && (AOP_TYPE(result) == AOP_CRY)){
6519 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6522 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6526 pic16_emitcode("clr","c");
6529 if (AOP_TYPE(right) == AOP_CRY){
6531 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6532 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6535 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6537 pic16_emitcode("rrc","a");
6538 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6544 pic16_outBitC(result);
6546 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6547 genIfxJump(ifx, "c");
6551 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6552 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6553 if((AOP_TYPE(right) == AOP_LIT) &&
6554 (AOP_TYPE(result) == AOP_CRY) &&
6555 (AOP_TYPE(left) != AOP_CRY)){
6556 int posbit = isLiteralBit(lit);
6560 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6563 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6569 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6570 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6572 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6573 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6576 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6577 size = AOP_SIZE(left);
6580 int bp = posbit, ofs=0;
6587 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6588 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
6592 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6593 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6595 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6602 symbol *tlbl = newiTempLabel(NULL);
6603 int sizel = AOP_SIZE(left);
6605 pic16_emitcode("setb","c");
6607 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6608 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6610 if((posbit = isLiteralBit(bytelit)) != 0)
6611 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6613 if(bytelit != 0x0FFL)
6614 pic16_emitcode("anl","a,%s",
6615 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6616 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6621 // bit = left & literal
6623 pic16_emitcode("clr","c");
6624 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6626 // if(left & literal)
6629 jmpTrueOrFalse(ifx, tlbl);
6633 pic16_outBitC(result);
6637 /* if left is same as result */
6638 if(pic16_sameRegs(AOP(result),AOP(left))){
6640 for(;size--; offset++,lit>>=8) {
6641 if(AOP_TYPE(right) == AOP_LIT){
6642 switch(lit & 0xff) {
6644 /* and'ing with 0 has clears the result */
6645 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6646 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6649 /* and'ing with 0xff is a nop when the result and left are the same */
6654 int p = my_powof2( (~lit) & 0xff );
6656 /* only one bit is set in the literal, so use a bcf instruction */
6657 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6658 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6661 pic16_emitcode("movlw","0x%x", (lit & 0xff));
6662 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6663 if(know_W != (lit&0xff))
6664 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6666 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6671 if (AOP_TYPE(left) == AOP_ACC) {
6672 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6674 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6675 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6682 // left & result in different registers
6683 if(AOP_TYPE(result) == AOP_CRY){
6685 // if(size), result in bit
6686 // if(!size && ifx), conditional oper: if(left & right)
6687 symbol *tlbl = newiTempLabel(NULL);
6688 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6690 pic16_emitcode("setb","c");
6692 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6693 pic16_emitcode("anl","a,%s",
6694 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6695 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6700 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6701 pic16_outBitC(result);
6703 jmpTrueOrFalse(ifx, tlbl);
6705 for(;(size--);offset++) {
6707 // result = left & right
6708 if(AOP_TYPE(right) == AOP_LIT){
6709 int t = (lit >> (offset*8)) & 0x0FFL;
6712 pic16_emitcode("clrf","%s",
6713 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6714 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6717 pic16_emitcode("movf","%s,w",
6718 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6719 pic16_emitcode("movwf","%s",
6720 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6721 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6722 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6725 pic16_emitcode("movlw","0x%x",t);
6726 pic16_emitcode("andwf","%s,w",
6727 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6728 pic16_emitcode("movwf","%s",
6729 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6731 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6732 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6733 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6738 if (AOP_TYPE(left) == AOP_ACC) {
6739 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6740 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6742 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6743 pic16_emitcode("andwf","%s,w",
6744 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6745 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6746 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6748 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6749 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6755 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6756 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6757 pic16_freeAsmop(result,NULL,ic,TRUE);
6760 /*-----------------------------------------------------------------*/
6761 /* genOr - code for or */
6762 /*-----------------------------------------------------------------*/
6763 static void genOr (iCode *ic, iCode *ifx)
6765 operand *left, *right, *result;
6767 unsigned long lit = 0L;
6769 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6771 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6772 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6773 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6775 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6777 /* if left is a literal & right is not then exchange them */
6778 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6779 AOP_NEEDSACC(left)) {
6780 operand *tmp = right ;
6785 /* if result = right then exchange them */
6786 if(pic16_sameRegs(AOP(result),AOP(right))){
6787 operand *tmp = right ;
6792 /* if right is bit then exchange them */
6793 if (AOP_TYPE(right) == AOP_CRY &&
6794 AOP_TYPE(left) != AOP_CRY){
6795 operand *tmp = right ;
6800 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6802 if(AOP_TYPE(right) == AOP_LIT)
6803 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6805 size = AOP_SIZE(result);
6809 if (AOP_TYPE(left) == AOP_CRY){
6810 if(AOP_TYPE(right) == AOP_LIT){
6811 // c = bit & literal;
6813 // lit != 0 => result = 1
6814 if(AOP_TYPE(result) == AOP_CRY){
6816 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6817 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6818 // AOP(result)->aopu.aop_dir,
6819 // AOP(result)->aopu.aop_dir);
6821 continueIfTrue(ifx);
6825 // lit == 0 => result = left
6826 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6828 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6831 if (AOP_TYPE(right) == AOP_CRY){
6832 if(pic16_sameRegs(AOP(result),AOP(left))){
6834 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6835 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6836 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6838 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6839 AOP(result)->aopu.aop_dir,
6840 AOP(result)->aopu.aop_dir);
6841 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6842 AOP(right)->aopu.aop_dir,
6843 AOP(right)->aopu.aop_dir);
6844 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6845 AOP(result)->aopu.aop_dir,
6846 AOP(result)->aopu.aop_dir);
6848 if( AOP_TYPE(result) == AOP_ACC) {
6849 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6850 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6851 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6852 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6856 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6857 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6858 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6859 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6861 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6862 AOP(result)->aopu.aop_dir,
6863 AOP(result)->aopu.aop_dir);
6864 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6865 AOP(right)->aopu.aop_dir,
6866 AOP(right)->aopu.aop_dir);
6867 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6868 AOP(left)->aopu.aop_dir,
6869 AOP(left)->aopu.aop_dir);
6870 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6871 AOP(result)->aopu.aop_dir,
6872 AOP(result)->aopu.aop_dir);
6877 symbol *tlbl = newiTempLabel(NULL);
6878 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6881 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6882 if( AOP_TYPE(right) == AOP_ACC) {
6883 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6885 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6886 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6891 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6892 pic16_emitcode(";XXX setb","c");
6893 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6894 AOP(left)->aopu.aop_dir,tlbl->key+100);
6895 pic16_toBoolean(right);
6896 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6897 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6898 jmpTrueOrFalse(ifx, tlbl);
6902 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6909 pic16_outBitC(result);
6911 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6912 genIfxJump(ifx, "c");
6916 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6917 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6918 if((AOP_TYPE(right) == AOP_LIT) &&
6919 (AOP_TYPE(result) == AOP_CRY) &&
6920 (AOP_TYPE(left) != AOP_CRY)){
6922 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6925 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6927 continueIfTrue(ifx);
6930 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6931 // lit = 0, result = boolean(left)
6933 pic16_emitcode(";XXX setb","c");
6934 pic16_toBoolean(right);
6936 symbol *tlbl = newiTempLabel(NULL);
6937 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6939 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6941 genIfxJump (ifx,"a");
6945 pic16_outBitC(result);
6949 /* if left is same as result */
6950 if(pic16_sameRegs(AOP(result),AOP(left))){
6952 for(;size--; offset++,lit>>=8) {
6953 if(AOP_TYPE(right) == AOP_LIT){
6954 if((lit & 0xff) == 0)
6955 /* or'ing with 0 has no effect */
6958 int p = my_powof2(lit & 0xff);
6960 /* only one bit is set in the literal, so use a bsf instruction */
6961 pic16_emitpcode(POC_BSF,
6962 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6964 if(know_W != (lit & 0xff))
6965 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6966 know_W = lit & 0xff;
6967 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6972 if (AOP_TYPE(left) == AOP_ACC) {
6973 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
6974 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6976 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6977 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6979 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6980 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6986 // left & result in different registers
6987 if(AOP_TYPE(result) == AOP_CRY){
6989 // if(size), result in bit
6990 // if(!size && ifx), conditional oper: if(left | right)
6991 symbol *tlbl = newiTempLabel(NULL);
6992 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6993 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6997 pic16_emitcode(";XXX setb","c");
6999 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7000 pic16_emitcode(";XXX orl","a,%s",
7001 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7002 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7007 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7008 pic16_outBitC(result);
7010 jmpTrueOrFalse(ifx, tlbl);
7011 } else for(;(size--);offset++){
7013 // result = left & right
7014 if(AOP_TYPE(right) == AOP_LIT){
7015 int t = (lit >> (offset*8)) & 0x0FFL;
7018 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7019 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7021 pic16_emitcode("movf","%s,w",
7022 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7023 pic16_emitcode("movwf","%s",
7024 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7027 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7028 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7029 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7031 pic16_emitcode("movlw","0x%x",t);
7032 pic16_emitcode("iorwf","%s,w",
7033 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7034 pic16_emitcode("movwf","%s",
7035 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7041 // faster than result <- left, anl result,right
7042 // and better if result is SFR
7043 if (AOP_TYPE(left) == AOP_ACC) {
7044 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7045 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7047 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7048 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7050 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7051 pic16_emitcode("iorwf","%s,w",
7052 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7054 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7055 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7060 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7061 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7062 pic16_freeAsmop(result,NULL,ic,TRUE);
7065 /*-----------------------------------------------------------------*/
7066 /* genXor - code for xclusive or */
7067 /*-----------------------------------------------------------------*/
7068 static void genXor (iCode *ic, iCode *ifx)
7070 operand *left, *right, *result;
7072 unsigned long lit = 0L;
7074 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7076 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7077 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7078 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7080 /* if left is a literal & right is not ||
7081 if left needs acc & right does not */
7082 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7083 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7084 operand *tmp = right ;
7089 /* if result = right then exchange them */
7090 if(pic16_sameRegs(AOP(result),AOP(right))){
7091 operand *tmp = right ;
7096 /* if right is bit then exchange them */
7097 if (AOP_TYPE(right) == AOP_CRY &&
7098 AOP_TYPE(left) != AOP_CRY){
7099 operand *tmp = right ;
7103 if(AOP_TYPE(right) == AOP_LIT)
7104 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7106 size = AOP_SIZE(result);
7110 if (AOP_TYPE(left) == AOP_CRY){
7111 if(AOP_TYPE(right) == AOP_LIT){
7112 // c = bit & literal;
7114 // lit>>1 != 0 => result = 1
7115 if(AOP_TYPE(result) == AOP_CRY){
7117 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
7118 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7120 continueIfTrue(ifx);
7123 pic16_emitcode("setb","c");
7127 // lit == 0, result = left
7128 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7130 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7132 // lit == 1, result = not(left)
7133 if(size && pic16_sameRegs(AOP(result),AOP(left))){
7134 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
7135 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
7136 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7139 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7140 pic16_emitcode("cpl","c");
7147 symbol *tlbl = newiTempLabel(NULL);
7148 if (AOP_TYPE(right) == AOP_CRY){
7150 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7153 int sizer = AOP_SIZE(right);
7155 // if val>>1 != 0, result = 1
7156 pic16_emitcode("setb","c");
7158 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7160 // test the msb of the lsb
7161 pic16_emitcode("anl","a,#0xfe");
7162 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7166 pic16_emitcode("rrc","a");
7168 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7169 pic16_emitcode("cpl","c");
7170 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7175 pic16_outBitC(result);
7177 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7178 genIfxJump(ifx, "c");
7182 if(pic16_sameRegs(AOP(result),AOP(left))){
7183 /* if left is same as result */
7184 for(;size--; offset++) {
7185 if(AOP_TYPE(right) == AOP_LIT){
7186 int t = (lit >> (offset*8)) & 0x0FFL;
7190 if (IS_AOP_PREG(left)) {
7191 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7192 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7193 pic16_aopPut(AOP(result),"a",offset);
7195 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7196 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7197 pic16_emitcode("xrl","%s,%s",
7198 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7199 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7202 if (AOP_TYPE(left) == AOP_ACC)
7203 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7205 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7206 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7208 if (IS_AOP_PREG(left)) {
7209 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7210 pic16_aopPut(AOP(result),"a",offset);
7212 pic16_emitcode("xrl","%s,a",
7213 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7219 // left & result in different registers
7220 if(AOP_TYPE(result) == AOP_CRY){
7222 // if(size), result in bit
7223 // if(!size && ifx), conditional oper: if(left ^ right)
7224 symbol *tlbl = newiTempLabel(NULL);
7225 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7227 pic16_emitcode("setb","c");
7229 if((AOP_TYPE(right) == AOP_LIT) &&
7230 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7231 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7233 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7234 pic16_emitcode("xrl","a,%s",
7235 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7237 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7242 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7243 pic16_outBitC(result);
7245 jmpTrueOrFalse(ifx, tlbl);
7246 } else for(;(size--);offset++){
7248 // result = left & right
7249 if(AOP_TYPE(right) == AOP_LIT){
7250 int t = (lit >> (offset*8)) & 0x0FFL;
7253 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7254 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7255 pic16_emitcode("movf","%s,w",
7256 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7257 pic16_emitcode("movwf","%s",
7258 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7261 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7262 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7263 pic16_emitcode("comf","%s,w",
7264 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7265 pic16_emitcode("movwf","%s",
7266 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7269 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7270 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7271 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7272 pic16_emitcode("movlw","0x%x",t);
7273 pic16_emitcode("xorwf","%s,w",
7274 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7275 pic16_emitcode("movwf","%s",
7276 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7282 // faster than result <- left, anl result,right
7283 // and better if result is SFR
7284 if (AOP_TYPE(left) == AOP_ACC) {
7285 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7286 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7288 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7289 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7290 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7291 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7293 if ( AOP_TYPE(result) != AOP_ACC){
7294 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7295 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7301 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7302 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7303 pic16_freeAsmop(result,NULL,ic,TRUE);
7306 /*-----------------------------------------------------------------*/
7307 /* genInline - write the inline code out */
7308 /*-----------------------------------------------------------------*/
7309 static void genInline (iCode *ic)
7311 char *buffer, *bp, *bp1;
7313 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7315 _G.inLine += (!options.asmpeep);
7317 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7318 strcpy(buffer,IC_INLINE(ic));
7320 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7322 /* emit each line as a code */
7328 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7336 /* print label, use this special format with NULL directive
7337 * to denote that the argument should not be indented with tab */
7338 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7345 if ((bp1 != bp) && *bp1)
7346 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7351 _G.inLine -= (!options.asmpeep);
7354 /*-----------------------------------------------------------------*/
7355 /* genRRC - rotate right with carry */
7356 /*-----------------------------------------------------------------*/
7357 static void genRRC (iCode *ic)
7359 operand *left , *result ;
7360 int size, offset = 0, same;
7362 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7364 /* rotate right with carry */
7366 result=IC_RESULT(ic);
7367 pic16_aopOp (left,ic,FALSE);
7368 pic16_aopOp (result,ic,FALSE);
7370 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7372 same = pic16_sameRegs(AOP(result),AOP(left));
7374 size = AOP_SIZE(result);
7376 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7378 /* get the lsb and put it into the carry */
7379 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7386 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7388 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7389 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7395 pic16_freeAsmop(left,NULL,ic,TRUE);
7396 pic16_freeAsmop(result,NULL,ic,TRUE);
7399 /*-----------------------------------------------------------------*/
7400 /* genRLC - generate code for rotate left with carry */
7401 /*-----------------------------------------------------------------*/
7402 static void genRLC (iCode *ic)
7404 operand *left , *result ;
7405 int size, offset = 0;
7408 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7409 /* rotate right with carry */
7411 result=IC_RESULT(ic);
7412 pic16_aopOp (left,ic,FALSE);
7413 pic16_aopOp (result,ic,FALSE);
7415 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7417 same = pic16_sameRegs(AOP(result),AOP(left));
7419 /* move it to the result */
7420 size = AOP_SIZE(result);
7422 /* get the msb and put it into the carry */
7423 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7430 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7432 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7433 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7440 pic16_freeAsmop(left,NULL,ic,TRUE);
7441 pic16_freeAsmop(result,NULL,ic,TRUE);
7445 /* gpasm can get the highest order bit with HIGH/UPPER
7446 * so the following probably is not needed -- VR */
7448 /*-----------------------------------------------------------------*/
7449 /* genGetHbit - generates code get highest order bit */
7450 /*-----------------------------------------------------------------*/
7451 static void genGetHbit (iCode *ic)
7453 operand *left, *result;
7455 result=IC_RESULT(ic);
7456 pic16_aopOp (left,ic,FALSE);
7457 pic16_aopOp (result,ic,FALSE);
7459 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7460 /* get the highest order byte into a */
7461 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7462 if(AOP_TYPE(result) == AOP_CRY){
7463 pic16_emitcode("rlc","a");
7464 pic16_outBitC(result);
7467 pic16_emitcode("rl","a");
7468 pic16_emitcode("anl","a,#0x01");
7469 pic16_outAcc(result);
7473 pic16_freeAsmop(left,NULL,ic,TRUE);
7474 pic16_freeAsmop(result,NULL,ic,TRUE);
7478 /*-----------------------------------------------------------------*/
7479 /* AccRol - rotate left accumulator by known count */
7480 /*-----------------------------------------------------------------*/
7481 static void AccRol (int shCount)
7483 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7484 shCount &= 0x0007; // shCount : 0..7
7489 pic16_emitcode("rl","a");
7492 pic16_emitcode("rl","a");
7493 pic16_emitcode("rl","a");
7496 pic16_emitcode("swap","a");
7497 pic16_emitcode("rr","a");
7500 pic16_emitcode("swap","a");
7503 pic16_emitcode("swap","a");
7504 pic16_emitcode("rl","a");
7507 pic16_emitcode("rr","a");
7508 pic16_emitcode("rr","a");
7511 pic16_emitcode("rr","a");
7517 /*-----------------------------------------------------------------*/
7518 /* AccLsh - left shift accumulator by known count */
7519 /*-----------------------------------------------------------------*/
7520 static void AccLsh (int shCount)
7522 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7528 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7531 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7532 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7535 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7536 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7539 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7542 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7543 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7546 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7547 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7550 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7554 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7557 /*-----------------------------------------------------------------*/
7558 /* AccRsh - right shift accumulator by known count */
7559 /*-----------------------------------------------------------------*/
7560 static void AccRsh (int shCount, int andmask)
7562 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7567 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7568 // andmask = 0; /* no need */
7571 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7572 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7573 // andmask = 0; /* no need */
7576 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7577 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7580 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7583 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7584 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7587 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7588 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7591 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7596 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7598 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7602 /*-----------------------------------------------------------------*/
7603 /* AccSRsh - signed right shift accumulator by known count */
7604 /*-----------------------------------------------------------------*/
7605 static void AccSRsh (int shCount)
7608 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7611 pic16_emitcode("mov","c,acc.7");
7612 pic16_emitcode("rrc","a");
7613 } else if(shCount == 2){
7614 pic16_emitcode("mov","c,acc.7");
7615 pic16_emitcode("rrc","a");
7616 pic16_emitcode("mov","c,acc.7");
7617 pic16_emitcode("rrc","a");
7619 tlbl = newiTempLabel(NULL);
7620 /* rotate right accumulator */
7621 AccRol(8 - shCount);
7622 /* and kill the higher order bits */
7623 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7624 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7625 pic16_emitcode("orl","a,#0x%02x",
7626 (unsigned char)~SRMask[shCount]);
7627 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7632 /*-----------------------------------------------------------------*/
7633 /* shiftR1Left2Result - shift right one byte from left to result */
7634 /*-----------------------------------------------------------------*/
7635 static void shiftR1Left2ResultSigned (operand *left, int offl,
7636 operand *result, int offr,
7641 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7643 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7647 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7649 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7651 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7652 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7658 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7660 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7662 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7663 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7665 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7666 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7672 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7674 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7675 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7678 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7679 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7680 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7682 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7683 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7685 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7689 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7690 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7691 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7692 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
7693 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7697 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7699 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7700 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7702 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7703 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
7704 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7705 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
7706 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7711 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7712 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7713 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7714 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7715 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7716 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7718 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7719 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7720 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7721 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7722 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7728 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7729 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7730 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7731 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7733 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7734 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7735 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7743 /*-----------------------------------------------------------------*/
7744 /* shiftR1Left2Result - shift right one byte from left to result */
7745 /*-----------------------------------------------------------------*/
7746 static void shiftR1Left2Result (operand *left, int offl,
7747 operand *result, int offr,
7748 int shCount, int sign)
7752 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7754 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7756 /* Copy the msb into the carry if signed. */
7758 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7768 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7770 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7771 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7777 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7779 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7780 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7783 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7788 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7790 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7791 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7794 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7795 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7796 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7797 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7801 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7802 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7803 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7807 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7808 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7809 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7811 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7816 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7817 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7818 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7819 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7820 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7825 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7826 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7827 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7836 /*-----------------------------------------------------------------*/
7837 /* shiftL1Left2Result - shift left one byte from left to result */
7838 /*-----------------------------------------------------------------*/
7839 static void shiftL1Left2Result (operand *left, int offl,
7840 operand *result, int offr, int shCount)
7845 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7847 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7848 DEBUGpic16_emitcode ("; ***","same = %d",same);
7849 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7851 /* shift left accumulator */
7852 //AccLsh(shCount); // don't comment out just yet...
7853 // pic16_aopPut(AOP(result),"a",offr);
7857 /* Shift left 1 bit position */
7858 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7860 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7862 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7863 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7867 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7868 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7869 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7870 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7873 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7874 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7875 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7876 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7877 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7880 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7881 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7882 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7885 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7886 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7887 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7888 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7891 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7892 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7893 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7894 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7895 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7898 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7899 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7900 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7904 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7909 /*-----------------------------------------------------------------*/
7910 /* movLeft2Result - move byte from left to result */
7911 /*-----------------------------------------------------------------*/
7912 static void movLeft2Result (operand *left, int offl,
7913 operand *result, int offr)
7916 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7917 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7918 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7920 if (*l == '@' && (IS_AOP_PREG(result))) {
7921 pic16_emitcode("mov","a,%s",l);
7922 pic16_aopPut(AOP(result),"a",offr);
7924 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7925 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7930 /*-----------------------------------------------------------------*/
7931 /* shiftL2Left2Result - shift left two bytes from left to result */
7932 /*-----------------------------------------------------------------*/
7933 static void shiftL2Left2Result (operand *left, int offl,
7934 operand *result, int offr, int shCount)
7936 int same = pic16_sameRegs(AOP(result), AOP(left));
7939 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7941 if (same && (offl != offr)) { // shift bytes
7944 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7945 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7947 } else { // just treat as different later on
7960 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7961 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7962 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7966 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7967 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7973 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7974 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7975 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7976 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7977 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7978 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7979 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7981 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7982 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7986 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7987 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7988 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7989 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7990 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7991 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7992 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7993 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7994 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7995 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7998 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7999 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8000 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8001 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8002 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8012 /* note, use a mov/add for the shift since the mov has a
8013 chance of getting optimized out */
8014 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8015 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8016 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8017 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8018 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8022 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8023 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8029 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8030 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8031 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8032 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8033 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8034 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8035 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8036 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8040 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8041 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8045 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8046 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8047 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8048 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8050 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8051 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8052 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8053 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8054 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8055 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8056 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8057 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8060 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8061 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8062 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8063 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8064 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8069 /*-----------------------------------------------------------------*/
8070 /* shiftR2Left2Result - shift right two bytes from left to result */
8071 /*-----------------------------------------------------------------*/
8072 static void shiftR2Left2Result (operand *left, int offl,
8073 operand *result, int offr,
8074 int shCount, int sign)
8076 int same = pic16_sameRegs(AOP(result), AOP(left));
8078 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8080 if (same && (offl != offr)) { // shift right bytes
8083 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8084 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8086 } else { // just treat as different later on
8098 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8103 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8104 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8106 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8107 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8108 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8109 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8114 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8117 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8118 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8125 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
8126 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
8127 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8129 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8130 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
8131 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8132 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8134 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8135 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8136 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8138 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8139 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8140 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8141 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8142 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8146 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8147 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8151 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
8152 pic16_emitpcode(POC_BTFSC,
8153 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
8154 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8162 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8163 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8165 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8166 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8167 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8168 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8170 pic16_emitpcode(POC_BTFSC,
8171 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8172 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8174 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8175 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8176 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8177 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8179 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8180 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8181 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8182 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8183 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8184 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8185 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8186 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8188 pic16_emitpcode(POC_BTFSC,
8189 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8190 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8192 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8193 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8200 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8201 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8202 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8203 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8206 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8208 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8213 /*-----------------------------------------------------------------*/
8214 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8215 /*-----------------------------------------------------------------*/
8216 static void shiftLLeftOrResult (operand *left, int offl,
8217 operand *result, int offr, int shCount)
8219 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8221 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8222 /* shift left accumulator */
8224 /* or with result */
8225 /* back to result */
8226 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8229 /*-----------------------------------------------------------------*/
8230 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8231 /*-----------------------------------------------------------------*/
8232 static void shiftRLeftOrResult (operand *left, int offl,
8233 operand *result, int offr, int shCount)
8235 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8237 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8238 /* shift right accumulator */
8240 /* or with result */
8241 /* back to result */
8242 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8245 /*-----------------------------------------------------------------*/
8246 /* genlshOne - left shift a one byte quantity by known count */
8247 /*-----------------------------------------------------------------*/
8248 static void genlshOne (operand *result, operand *left, int shCount)
8250 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8251 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8254 /*-----------------------------------------------------------------*/
8255 /* genlshTwo - left shift two bytes by known amount != 0 */
8256 /*-----------------------------------------------------------------*/
8257 static void genlshTwo (operand *result,operand *left, int shCount)
8261 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8262 size = pic16_getDataSize(result);
8264 /* if shCount >= 8 */
8270 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8272 movLeft2Result(left, LSB, result, MSB16);
8274 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8277 /* 1 <= shCount <= 7 */
8280 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8282 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8286 /*-----------------------------------------------------------------*/
8287 /* shiftLLong - shift left one long from left to result */
8288 /* offr = LSB or MSB16 */
8289 /*-----------------------------------------------------------------*/
8290 static void shiftLLong (operand *left, operand *result, int offr )
8292 int size = AOP_SIZE(result);
8293 int same = pic16_sameRegs(AOP(left),AOP(result));
8296 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8298 if (same && (offr == MSB16)) { //shift one byte
8299 for(i=size-1;i>=MSB16;i--) {
8300 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8301 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8304 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8307 if (size >= LSB+offr ){
8309 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8311 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8312 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8316 if(size >= MSB16+offr){
8318 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8320 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8321 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8325 if(size >= MSB24+offr){
8327 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8329 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8330 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8334 if(size > MSB32+offr){
8336 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8338 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8339 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8343 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8347 /*-----------------------------------------------------------------*/
8348 /* genlshFour - shift four byte by a known amount != 0 */
8349 /*-----------------------------------------------------------------*/
8350 static void genlshFour (operand *result, operand *left, int shCount)
8354 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8355 size = AOP_SIZE(result);
8357 /* if shifting more that 3 bytes */
8358 if (shCount >= 24 ) {
8361 /* lowest order of left goes to the highest
8362 order of the destination */
8363 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8365 movLeft2Result(left, LSB, result, MSB32);
8367 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8368 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8369 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8374 /* more than two bytes */
8375 else if ( shCount >= 16 ) {
8376 /* lower order two bytes goes to higher order two bytes */
8378 /* if some more remaining */
8380 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8382 movLeft2Result(left, MSB16, result, MSB32);
8383 movLeft2Result(left, LSB, result, MSB24);
8385 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8386 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8390 /* if more than 1 byte */
8391 else if ( shCount >= 8 ) {
8392 /* lower order three bytes goes to higher order three bytes */
8396 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8398 movLeft2Result(left, LSB, result, MSB16);
8400 else{ /* size = 4 */
8402 movLeft2Result(left, MSB24, result, MSB32);
8403 movLeft2Result(left, MSB16, result, MSB24);
8404 movLeft2Result(left, LSB, result, MSB16);
8405 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8407 else if(shCount == 1)
8408 shiftLLong(left, result, MSB16);
8410 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8411 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8412 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8413 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8418 /* 1 <= shCount <= 7 */
8419 else if(shCount <= 3)
8421 shiftLLong(left, result, LSB);
8422 while(--shCount >= 1)
8423 shiftLLong(result, result, LSB);
8425 /* 3 <= shCount <= 7, optimize */
8427 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8428 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8429 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8433 /*-----------------------------------------------------------------*/
8434 /* genLeftShiftLiteral - left shifting by known count */
8435 /*-----------------------------------------------------------------*/
8436 static void genLeftShiftLiteral (operand *left,
8441 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8444 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8445 pic16_freeAsmop(right,NULL,ic,TRUE);
8447 pic16_aopOp(left,ic,FALSE);
8448 pic16_aopOp(result,ic,FALSE);
8450 size = getSize(operandType(result));
8453 pic16_emitcode("; shift left ","result %d, left %d",size,
8457 /* I suppose that the left size >= result size */
8460 movLeft2Result(left, size, result, size);
8464 else if(shCount >= (size * 8))
8466 pic16_aopPut(AOP(result),zero,size);
8470 genlshOne (result,left,shCount);
8475 genlshTwo (result,left,shCount);
8479 genlshFour (result,left,shCount);
8483 pic16_freeAsmop(left,NULL,ic,TRUE);
8484 pic16_freeAsmop(result,NULL,ic,TRUE);
8487 /*-----------------------------------------------------------------*
8488 * genMultiAsm - repeat assembly instruction for size of register.
8489 * if endian == 1, then the high byte (i.e base address + size of
8490 * register) is used first else the low byte is used first;
8491 *-----------------------------------------------------------------*/
8492 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8497 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8510 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
8515 /*-----------------------------------------------------------------*/
8516 /* genLeftShift - generates code for left shifting */
8517 /*-----------------------------------------------------------------*/
8518 static void genLeftShift (iCode *ic)
8520 operand *left,*right, *result;
8523 symbol *tlbl , *tlbl1;
8526 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8528 right = IC_RIGHT(ic);
8530 result = IC_RESULT(ic);
8532 pic16_aopOp(right,ic,FALSE);
8534 /* if the shift count is known then do it
8535 as efficiently as possible */
8536 if (AOP_TYPE(right) == AOP_LIT) {
8537 genLeftShiftLiteral (left,right,result,ic);
8541 /* shift count is unknown then we have to form
8542 a loop get the loop count in B : Note: we take
8543 only the lower order byte since shifting
8544 more that 32 bits make no sense anyway, ( the
8545 largest size of an object can be only 32 bits ) */
8548 pic16_aopOp(left,ic,FALSE);
8549 pic16_aopOp(result,ic,FALSE);
8551 /* now move the left to the result if they are not the
8553 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8554 AOP_SIZE(result) > 1) {
8556 size = AOP_SIZE(result);
8559 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8560 if (*l == '@' && (IS_AOP_PREG(result))) {
8562 pic16_emitcode("mov","a,%s",l);
8563 pic16_aopPut(AOP(result),"a",offset);
8565 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8566 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8567 //pic16_aopPut(AOP(result),l,offset);
8573 size = AOP_SIZE(result);
8575 /* if it is only one byte then */
8577 if(optimized_for_speed) {
8578 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8579 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8580 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8581 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8582 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8583 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8584 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8585 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
8586 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
8587 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
8588 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8589 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8592 tlbl = newiTempLabel(NULL);
8593 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8594 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8595 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8598 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8599 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8600 pic16_emitpLabel(tlbl->key);
8601 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8602 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8604 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8609 if (pic16_sameRegs(AOP(left),AOP(result))) {
8611 tlbl = newiTempLabel(NULL);
8612 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8613 genMultiAsm(POC_RRCF, result, size,1);
8614 pic16_emitpLabel(tlbl->key);
8615 genMultiAsm(POC_RLCF, result, size,0);
8616 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8618 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8622 //tlbl = newiTempLabel(NULL);
8624 //tlbl1 = newiTempLabel(NULL);
8626 //reAdjustPreg(AOP(result));
8628 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8629 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8630 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8632 //pic16_emitcode("add","a,acc");
8633 //pic16_aopPut(AOP(result),"a",offset++);
8635 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8637 // pic16_emitcode("rlc","a");
8638 // pic16_aopPut(AOP(result),"a",offset++);
8640 //reAdjustPreg(AOP(result));
8642 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8643 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8646 tlbl = newiTempLabel(NULL);
8647 tlbl1= newiTempLabel(NULL);
8649 size = AOP_SIZE(result);
8652 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8654 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8656 /* offset should be 0, 1 or 3 */
8658 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8660 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8662 pic16_emitpcode(POC_MOVWF, pctemp);
8665 pic16_emitpLabel(tlbl->key);
8668 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8670 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
8672 pic16_emitpcode(POC_DECFSZ, pctemp);
8673 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8674 pic16_emitpLabel(tlbl1->key);
8676 pic16_popReleaseTempReg(pctemp);
8680 pic16_freeAsmop (right,NULL,ic,TRUE);
8681 pic16_freeAsmop(left,NULL,ic,TRUE);
8682 pic16_freeAsmop(result,NULL,ic,TRUE);
8685 /*-----------------------------------------------------------------*/
8686 /* genrshOne - right shift a one byte quantity by known count */
8687 /*-----------------------------------------------------------------*/
8688 static void genrshOne (operand *result, operand *left,
8689 int shCount, int sign)
8691 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8692 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8695 /*-----------------------------------------------------------------*/
8696 /* genrshTwo - right shift two bytes by known amount != 0 */
8697 /*-----------------------------------------------------------------*/
8698 static void genrshTwo (operand *result,operand *left,
8699 int shCount, int sign)
8701 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8702 /* if shCount >= 8 */
8706 shiftR1Left2Result(left, MSB16, result, LSB,
8709 movLeft2Result(left, MSB16, result, LSB);
8711 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8714 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8715 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8719 /* 1 <= shCount <= 7 */
8721 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
8724 /*-----------------------------------------------------------------*/
8725 /* shiftRLong - shift right one long from left to result */
8726 /* offl = LSB or MSB16 */
8727 /*-----------------------------------------------------------------*/
8728 static void shiftRLong (operand *left, int offl,
8729 operand *result, int sign)
8731 int size = AOP_SIZE(result);
8732 int same = pic16_sameRegs(AOP(left),AOP(result));
8734 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8736 if (same && (offl == MSB16)) { //shift one byte right
8737 for(i=MSB16;i<size;i++) {
8738 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8739 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8744 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8750 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8752 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8753 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8757 /* add sign of "a" */
8758 pic16_addSign(result, MSB32, sign);
8762 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8764 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8765 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8769 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8771 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8772 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8776 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8779 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8780 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8785 /*-----------------------------------------------------------------*/
8786 /* genrshFour - shift four byte by a known amount != 0 */
8787 /*-----------------------------------------------------------------*/
8788 static void genrshFour (operand *result, operand *left,
8789 int shCount, int sign)
8791 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8792 /* if shifting more that 3 bytes */
8793 if(shCount >= 24 ) {
8796 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8798 movLeft2Result(left, MSB32, result, LSB);
8800 pic16_addSign(result, MSB16, sign);
8802 else if(shCount >= 16){
8805 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8807 movLeft2Result(left, MSB24, result, LSB);
8808 movLeft2Result(left, MSB32, result, MSB16);
8810 pic16_addSign(result, MSB24, sign);
8812 else if(shCount >= 8){
8815 shiftRLong(left, MSB16, result, sign);
8816 else if(shCount == 0){
8817 movLeft2Result(left, MSB16, result, LSB);
8818 movLeft2Result(left, MSB24, result, MSB16);
8819 movLeft2Result(left, MSB32, result, MSB24);
8820 pic16_addSign(result, MSB32, sign);
8822 else{ //shcount >= 2
8823 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8824 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8825 /* the last shift is signed */
8826 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8827 pic16_addSign(result, MSB32, sign);
8830 else{ /* 1 <= shCount <= 7 */
8832 shiftRLong(left, LSB, result, sign);
8834 shiftRLong(result, LSB, result, sign);
8837 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8838 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8839 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8844 /*-----------------------------------------------------------------*/
8845 /* genRightShiftLiteral - right shifting by known count */
8846 /*-----------------------------------------------------------------*/
8847 static void genRightShiftLiteral (operand *left,
8853 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8856 pic16_freeAsmop(right,NULL,ic,TRUE);
8858 pic16_aopOp(left,ic,FALSE);
8859 pic16_aopOp(result,ic,FALSE);
8861 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8864 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8868 lsize = pic16_getDataSize(left);
8869 res_size = pic16_getDataSize(result);
8870 /* test the LEFT size !!! */
8872 /* I suppose that the left size >= result size */
8875 movLeft2Result(left, lsize, result, res_size);
8878 else if(shCount >= (lsize * 8)){
8881 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8883 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8884 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8889 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8890 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8891 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8893 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8898 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8905 genrshOne (result,left,shCount,sign);
8909 genrshTwo (result,left,shCount,sign);
8913 genrshFour (result,left,shCount,sign);
8921 pic16_freeAsmop(left,NULL,ic,TRUE);
8922 pic16_freeAsmop(result,NULL,ic,TRUE);
8925 /*-----------------------------------------------------------------*/
8926 /* genSignedRightShift - right shift of signed number */
8927 /*-----------------------------------------------------------------*/
8928 static void genSignedRightShift (iCode *ic)
8930 operand *right, *left, *result;
8933 symbol *tlbl, *tlbl1 ;
8936 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8938 /* we do it the hard way put the shift count in b
8939 and loop thru preserving the sign */
8940 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8942 right = IC_RIGHT(ic);
8944 result = IC_RESULT(ic);
8946 pic16_aopOp(right,ic,FALSE);
8947 pic16_aopOp(left,ic,FALSE);
8948 pic16_aopOp(result,ic,FALSE);
8951 if ( AOP_TYPE(right) == AOP_LIT) {
8952 genRightShiftLiteral (left,right,result,ic,1);
8955 /* shift count is unknown then we have to form
8956 a loop get the loop count in B : Note: we take
8957 only the lower order byte since shifting
8958 more that 32 bits make no sense anyway, ( the
8959 largest size of an object can be only 32 bits ) */
8961 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8962 //pic16_emitcode("inc","b");
8963 //pic16_freeAsmop (right,NULL,ic,TRUE);
8964 //pic16_aopOp(left,ic,FALSE);
8965 //pic16_aopOp(result,ic,FALSE);
8967 /* now move the left to the result if they are not the
8969 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8970 AOP_SIZE(result) > 1) {
8972 size = AOP_SIZE(result);
8976 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8977 if (*l == '@' && IS_AOP_PREG(result)) {
8979 pic16_emitcode("mov","a,%s",l);
8980 pic16_aopPut(AOP(result),"a",offset);
8982 pic16_aopPut(AOP(result),l,offset);
8984 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8985 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8991 /* mov the highest order bit to OVR */
8992 tlbl = newiTempLabel(NULL);
8993 tlbl1= newiTempLabel(NULL);
8995 size = AOP_SIZE(result);
8998 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
9000 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9002 /* offset should be 0, 1 or 3 */
9003 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
9005 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9007 pic16_emitpcode(POC_MOVWF, pctemp);
9010 pic16_emitpLabel(tlbl->key);
9012 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
9013 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
9016 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
9019 pic16_emitpcode(POC_DECFSZ, pctemp);
9020 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9021 pic16_emitpLabel(tlbl1->key);
9023 pic16_popReleaseTempReg(pctemp);
9025 size = AOP_SIZE(result);
9027 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
9028 pic16_emitcode("rlc","a");
9029 pic16_emitcode("mov","ov,c");
9030 /* if it is only one byte then */
9032 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9034 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9035 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9036 pic16_emitcode("mov","c,ov");
9037 pic16_emitcode("rrc","a");
9038 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9039 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9040 pic16_aopPut(AOP(result),"a",0);
9044 reAdjustPreg(AOP(result));
9045 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9046 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9047 pic16_emitcode("mov","c,ov");
9049 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9051 pic16_emitcode("rrc","a");
9052 pic16_aopPut(AOP(result),"a",offset--);
9054 reAdjustPreg(AOP(result));
9055 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9056 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9061 pic16_freeAsmop(left,NULL,ic,TRUE);
9062 pic16_freeAsmop(result,NULL,ic,TRUE);
9063 pic16_freeAsmop(right,NULL,ic,TRUE);
9066 /*-----------------------------------------------------------------*/
9067 /* genRightShift - generate code for right shifting */
9068 /*-----------------------------------------------------------------*/
9069 static void genRightShift (iCode *ic)
9071 operand *right, *left, *result;
9075 symbol *tlbl, *tlbl1 ;
9077 /* if signed then we do it the hard way preserve the
9078 sign bit moving it inwards */
9079 letype = getSpec(operandType(IC_LEFT(ic)));
9080 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9082 if (!SPEC_USIGN(letype)) {
9083 genSignedRightShift (ic);
9087 /* signed & unsigned types are treated the same : i.e. the
9088 signed is NOT propagated inwards : quoting from the
9089 ANSI - standard : "for E1 >> E2, is equivalent to division
9090 by 2**E2 if unsigned or if it has a non-negative value,
9091 otherwise the result is implementation defined ", MY definition
9092 is that the sign does not get propagated */
9094 right = IC_RIGHT(ic);
9096 result = IC_RESULT(ic);
9098 pic16_aopOp(right,ic,FALSE);
9100 /* if the shift count is known then do it
9101 as efficiently as possible */
9102 if (AOP_TYPE(right) == AOP_LIT) {
9103 genRightShiftLiteral (left,right,result,ic, 0);
9107 /* shift count is unknown then we have to form
9108 a loop get the loop count in B : Note: we take
9109 only the lower order byte since shifting
9110 more that 32 bits make no sense anyway, ( the
9111 largest size of an object can be only 32 bits ) */
9113 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9114 pic16_emitcode("inc","b");
9115 pic16_aopOp(left,ic,FALSE);
9116 pic16_aopOp(result,ic,FALSE);
9118 /* now move the left to the result if they are not the
9120 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9121 AOP_SIZE(result) > 1) {
9123 size = AOP_SIZE(result);
9126 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9127 if (*l == '@' && IS_AOP_PREG(result)) {
9129 pic16_emitcode("mov","a,%s",l);
9130 pic16_aopPut(AOP(result),"a",offset);
9132 pic16_aopPut(AOP(result),l,offset);
9137 tlbl = newiTempLabel(NULL);
9138 tlbl1= newiTempLabel(NULL);
9139 size = AOP_SIZE(result);
9142 /* if it is only one byte then */
9145 tlbl = newiTempLabel(NULL);
9146 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9147 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9148 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9151 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9152 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9153 pic16_emitpLabel(tlbl->key);
9154 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9155 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9157 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9162 reAdjustPreg(AOP(result));
9163 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9164 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9167 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9169 pic16_emitcode("rrc","a");
9170 pic16_aopPut(AOP(result),"a",offset--);
9172 reAdjustPreg(AOP(result));
9174 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9175 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9178 pic16_freeAsmop(left,NULL,ic,TRUE);
9179 pic16_freeAsmop (right,NULL,ic,TRUE);
9180 pic16_freeAsmop(result,NULL,ic,TRUE);
9183 /*-----------------------------------------------------------------*/
9184 /* genUnpackBits - generates code for unpacking bits */
9185 /*-----------------------------------------------------------------*/
9186 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
9193 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9194 etype = getSpec(operandType(result));
9196 /* read the first byte */
9203 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9206 pic16_emitcode("clr","a");
9207 pic16_emitcode("movc","a","@a+dptr");
9212 /* if we have bitdisplacement then it fits */
9213 /* into this byte completely or if length is */
9214 /* less than a byte */
9215 if ((shCnt = SPEC_BSTR(etype)) ||
9216 (SPEC_BLEN(etype) <= 8)) {
9218 /* shift right acc */
9221 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9222 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9224 /* VR -- normally I would use the following, but since we use the hack,
9225 * to avoid the masking from AccRsh, why not mask it right now? */
9228 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9231 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9237 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9238 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9241 /* bit field did not fit in a byte */
9242 rlen = SPEC_BLEN(etype) - 8;
9243 pic16_aopPut(AOP(result),"a",offset++);
9250 pic16_emitcode("inc","%s",rname);
9251 pic16_emitcode("mov","a,@%s",rname);
9255 pic16_emitcode("inc","%s",rname);
9256 pic16_emitcode("movx","a,@%s",rname);
9260 pic16_emitcode("inc","dptr");
9261 pic16_emitcode("movx","a,@dptr");
9265 pic16_emitcode("clr","a");
9266 pic16_emitcode("inc","dptr");
9267 pic16_emitcode("movc","a","@a+dptr");
9271 pic16_emitcode("inc","dptr");
9272 pic16_emitcode("lcall","__gptrget");
9277 /* if we are done */
9281 pic16_aopPut(AOP(result),"a",offset++);
9286 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9287 pic16_aopPut(AOP(result),"a",offset);
9294 static void genDataPointerGet(operand *left,
9298 int size, offset = 0, leoffset=0 ;
9300 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9301 pic16_aopOp(result, ic, FALSE);
9303 size = AOP_SIZE(result);
9304 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9308 /* The following tests may save a redudant movff instruction when
9309 * accessing unions */
9311 /* if they are the same */
9312 if (operandsEqu (left, result)) {
9313 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9319 /* if they are the same registers */
9320 if (pic16_sameRegs(AOP(left),AOP(result))) {
9321 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9327 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9328 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9329 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9336 if ( AOP_TYPE(left) == AOP_PCODE) {
9337 fprintf(stderr,"genDataPointerGet %s, %d\n",
9338 AOP(left)->aopu.pcop->name,
9339 (AOP(left)->aopu.pcop->type == PO_DIR)?
9340 PCOR(AOP(left)->aopu.pcop)->instance:
9341 PCOI(AOP(left)->aopu.pcop)->offset);
9345 if(AOP(left)->aopu.pcop->type == PO_DIR)
9346 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9348 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9351 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9353 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9354 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9355 mov2w(AOP(left), offset); // patch 8
9356 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9358 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9359 pic16_popGet(AOP(left), offset), //patch 8
9360 pic16_popGet(AOP(result), offset)));
9368 pic16_freeAsmop(result,NULL,ic,TRUE);
9371 void pic16_loadFSR0(operand *op)
9373 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9377 /*-----------------------------------------------------------------*/
9378 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
9379 /*-----------------------------------------------------------------*/
9380 static void genNearPointerGet (operand *left,
9385 //regs *preg = NULL ;
9386 sym_link *rtype, *retype;
9387 sym_link *ltype = operandType(left);
9389 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9390 rtype = operandType(result);
9391 retype= getSpec(rtype);
9393 pic16_aopOp(left,ic,FALSE);
9395 // pic16_DumpOp("(left)",left);
9396 // pic16_DumpOp("(result)",result);
9398 /* if left is rematerialisable and
9399 * result is not bit variable type and
9400 * the left is pointer to data space i.e
9401 * lower 128 bytes of space */
9402 if (AOP_TYPE(left) == AOP_PCODE
9403 && !IS_BITFIELD(retype)
9404 && DCL_TYPE(ltype) == POINTER) {
9406 genDataPointerGet (left,result,ic);
9407 pic16_freeAsmop(left, NULL, ic, TRUE);
9411 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9413 /* if the value is already in a pointer register
9414 * then don't need anything more */
9415 if (!AOP_INPREG(AOP(left))) {
9416 /* otherwise get a free pointer register */
9417 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9419 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9420 if( (AOP_TYPE(left) == AOP_PCODE)
9421 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9422 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9424 if(!IS_BITFIELD(retype))
9425 pic16_loadFSR0( left ); // patch 10
9427 // set up FSR0 with address from left
9428 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9429 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9433 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9435 pic16_aopOp (result,ic,FALSE);
9437 /* if bitfield then unpack the bits */
9438 if (IS_BITFIELD(retype))
9439 genUnpackBits (result, left, NULL, POINTER);
9441 /* we have can just get the values */
9442 int size = AOP_SIZE(result);
9445 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9448 /* fsr0 is loaded already -- VR */
9449 // pic16_loadFSR0( left );
9451 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9452 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9456 pic16_emitpcode(POC_MOVFF,
9457 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9458 pic16_popGet(AOP(result), offset++)));
9460 pic16_emitpcode(POC_MOVFF,
9461 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9462 pic16_popGet(AOP(result), offset++)));
9466 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9467 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9469 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9473 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9475 pic16_emitcode("mov","a,@%s",rname);
9476 pic16_aopPut(AOP(result),"a",offset);
9478 sprintf(buffer,"@%s",rname);
9479 pic16_aopPut(AOP(result),buffer,offset);
9483 pic16_emitcode("inc","%s",rname);
9488 /* now some housekeeping stuff */
9490 /* we had to allocate for this iCode */
9491 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9492 pic16_freeAsmop(NULL,aop,ic,TRUE);
9494 /* we did not allocate which means left
9495 already in a pointer register, then
9496 if size > 0 && this could be used again
9497 we have to point it back to where it
9499 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9500 if (AOP_SIZE(result) > 1 &&
9501 !OP_SYMBOL(left)->remat &&
9502 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9504 // int size = AOP_SIZE(result) - 1;
9506 // pic16_emitcode("dec","%s",rname);
9511 pic16_freeAsmop(left,NULL,ic,TRUE);
9512 pic16_freeAsmop(result,NULL,ic,TRUE);
9516 /*-----------------------------------------------------------------*/
9517 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
9518 /*-----------------------------------------------------------------*/
9519 static void genPagedPointerGet (operand *left,
9526 sym_link *rtype, *retype;
9528 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9530 rtype = operandType(result);
9531 retype= getSpec(rtype);
9533 pic16_aopOp(left,ic,FALSE);
9535 /* if the value is already in a pointer register
9536 then don't need anything more */
9537 if (!AOP_INPREG(AOP(left))) {
9538 /* otherwise get a free pointer register */
9540 preg = getFreePtr(ic,&aop,FALSE);
9541 pic16_emitcode("mov","%s,%s",
9543 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9544 rname = preg->name ;
9546 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9548 pic16_freeAsmop(left,NULL,ic,TRUE);
9549 pic16_aopOp (result,ic,FALSE);
9551 /* if bitfield then unpack the bits */
9552 if (IS_BITFIELD(retype))
9553 genUnpackBits (result,left,rname,PPOINTER);
9555 /* we have can just get the values */
9556 int size = AOP_SIZE(result);
9561 pic16_emitcode("movx","a,@%s",rname);
9562 pic16_aopPut(AOP(result),"a",offset);
9567 pic16_emitcode("inc","%s",rname);
9571 /* now some housekeeping stuff */
9573 /* we had to allocate for this iCode */
9574 pic16_freeAsmop(NULL,aop,ic,TRUE);
9576 /* we did not allocate which means left
9577 already in a pointer register, then
9578 if size > 0 && this could be used again
9579 we have to point it back to where it
9581 if (AOP_SIZE(result) > 1 &&
9582 !OP_SYMBOL(left)->remat &&
9583 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9585 int size = AOP_SIZE(result) - 1;
9587 pic16_emitcode("dec","%s",rname);
9592 pic16_freeAsmop(result,NULL,ic,TRUE);
9597 /*-----------------------------------------------------------------*/
9598 /* genFarPointerGet - gget value from far space */
9599 /*-----------------------------------------------------------------*/
9600 static void genFarPointerGet (operand *left,
9601 operand *result, iCode *ic)
9604 sym_link *retype = getSpec(operandType(result));
9606 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9608 pic16_aopOp(left,ic,FALSE);
9610 /* if the operand is already in dptr
9611 then we do nothing else we move the value to dptr */
9612 if (AOP_TYPE(left) != AOP_STR) {
9613 /* if this is remateriazable */
9614 if (AOP_TYPE(left) == AOP_IMMD)
9615 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9616 else { /* we need to get it byte by byte */
9617 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9618 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9619 if (options.model == MODEL_FLAT24)
9621 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9625 /* so dptr know contains the address */
9626 pic16_freeAsmop(left,NULL,ic,TRUE);
9627 pic16_aopOp(result,ic,FALSE);
9629 /* if bit then unpack */
9630 if (IS_BITFIELD(retype))
9631 genUnpackBits(result,left,"dptr",FPOINTER);
9633 size = AOP_SIZE(result);
9637 pic16_emitcode("movx","a,@dptr");
9638 pic16_aopPut(AOP(result),"a",offset++);
9640 pic16_emitcode("inc","dptr");
9644 pic16_freeAsmop(result,NULL,ic,TRUE);
9647 /*-----------------------------------------------------------------*/
9648 /* genCodePointerGet - get value from code space */
9649 /*-----------------------------------------------------------------*/
9650 static void genCodePointerGet (operand *left,
9651 operand *result, iCode *ic)
9654 sym_link *retype = getSpec(operandType(result));
9656 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9658 pic16_aopOp(left,ic,FALSE);
9660 /* if the operand is already in dptr
9661 then we do nothing else we move the value to dptr */
9662 if (AOP_TYPE(left) != AOP_STR) {
9663 /* if this is remateriazable */
9664 if (AOP_TYPE(left) == AOP_IMMD)
9665 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9666 else { /* we need to get it byte by byte */
9667 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9668 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9669 if (options.model == MODEL_FLAT24)
9671 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9675 /* so dptr know contains the address */
9676 pic16_freeAsmop(left,NULL,ic,TRUE);
9677 pic16_aopOp(result,ic,FALSE);
9679 /* if bit then unpack */
9680 if (IS_BITFIELD(retype))
9681 genUnpackBits(result,left,"dptr",CPOINTER);
9683 size = AOP_SIZE(result);
9687 pic16_emitcode("clr","a");
9688 pic16_emitcode("movc","a,@a+dptr");
9689 pic16_aopPut(AOP(result),"a",offset++);
9691 pic16_emitcode("inc","dptr");
9695 pic16_freeAsmop(result,NULL,ic,TRUE);
9698 /*-----------------------------------------------------------------*/
9699 /* genGenPointerGet - gget value from generic pointer space */
9700 /*-----------------------------------------------------------------*/
9701 static void genGenPointerGet (operand *left,
9702 operand *result, iCode *ic)
9704 int size, offset, lit;
9705 sym_link *retype = getSpec(operandType(result));
9707 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9708 pic16_aopOp(left,ic,FALSE);
9709 pic16_aopOp(result,ic,FALSE);
9710 size = AOP_SIZE(result);
9712 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9714 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9716 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9717 // load FSR0 from immediate
9718 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9720 // pic16_loadFSR0( left );
9725 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9727 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9734 else { /* we need to get it byte by byte */
9735 // set up FSR0 with address from left
9736 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9737 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9743 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9745 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9752 /* if bit then unpack */
9753 if (IS_BITFIELD(retype))
9754 genUnpackBits(result,left,"BAD",GPOINTER);
9757 pic16_freeAsmop(left,NULL,ic,TRUE);
9758 pic16_freeAsmop(result,NULL,ic,TRUE);
9762 /*-----------------------------------------------------------------*/
9763 /* genConstPointerGet - get value from const generic pointer space */
9764 /*-----------------------------------------------------------------*/
9765 static void genConstPointerGet (operand *left,
9766 operand *result, iCode *ic)
9768 //sym_link *retype = getSpec(operandType(result));
9769 // symbol *albl = newiTempLabel(NULL); // patch 15
9770 // symbol *blbl = newiTempLabel(NULL); //
9771 // PIC_OPCODE poc; // patch 15
9775 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9776 pic16_aopOp(left,ic,FALSE);
9777 pic16_aopOp(result,ic,TRUE);
9778 size = AOP_SIZE(result);
9780 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9782 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9784 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9785 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9786 pic16_emitpLabel(albl->key);
9788 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9790 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9791 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9792 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9793 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9794 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9796 pic16_emitpLabel(blbl->key);
9798 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9802 // set up table pointer
9803 if( (AOP_TYPE(left) == AOP_PCODE)
9804 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9805 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
9807 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9808 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9809 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9810 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9811 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9812 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9816 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9817 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9818 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9824 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9825 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9829 pic16_freeAsmop(left,NULL,ic,TRUE);
9830 pic16_freeAsmop(result,NULL,ic,TRUE);
9835 /*-----------------------------------------------------------------*/
9836 /* genPointerGet - generate code for pointer get */
9837 /*-----------------------------------------------------------------*/
9838 static void genPointerGet (iCode *ic)
9840 operand *left, *result ;
9841 sym_link *type, *etype;
9844 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9847 result = IC_RESULT(ic) ;
9849 /* depending on the type of pointer we need to
9850 move it to the correct pointer register */
9851 type = operandType(left);
9852 etype = getSpec(type);
9855 if (IS_PTR_CONST(type))
9857 if (IS_CODEPTR(type))
9859 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9861 /* if left is of type of pointer then it is simple */
9862 if (IS_PTR(type) && !IS_FUNC(type->next))
9863 p_type = DCL_TYPE(type);
9865 /* we have to go by the storage class */
9866 p_type = PTR_TYPE(SPEC_OCLS(etype));
9868 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9870 if (SPEC_OCLS(etype)->codesp ) {
9871 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9872 //p_type = CPOINTER ;
9875 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9876 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9877 /*p_type = FPOINTER ;*/
9879 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9880 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9881 /* p_type = PPOINTER; */
9883 if (SPEC_OCLS(etype) == idata )
9884 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9885 /* p_type = IPOINTER; */
9887 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9888 /* p_type = POINTER ; */
9891 /* now that we have the pointer type we assign
9892 the pointer values */
9897 genNearPointerGet (left,result,ic);
9901 genPagedPointerGet(left,result,ic);
9905 genFarPointerGet (left,result,ic);
9909 genConstPointerGet (left,result,ic);
9910 //pic16_emitcodePointerGet (left,result,ic);
9915 if (IS_PTR_CONST(type))
9916 genConstPointerGet (left,result,ic);
9919 genGenPointerGet (left,result,ic);
9923 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9924 "genPointerGet: illegal pointer type");
9930 /*-----------------------------------------------------------------*/
9931 /* genPackBits - generates code for packed bit storage */
9932 /*-----------------------------------------------------------------*/
9933 static void genPackBits (sym_link *etype , operand *result,
9935 char *rname, int p_type)
9943 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9944 blen = SPEC_BLEN(etype);
9945 bstr = SPEC_BSTR(etype);
9947 if(AOP_TYPE(right) == AOP_LIT) {
9948 if((blen == 1) && (bstr < 8)) {
9950 /* it is a single bit, so use the appropriate bit instructions */
9952 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9954 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9955 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9956 if((p_type == POINTER) && (result)) {
9957 /* workaround to reduce the extra lfsr instruction */
9959 pic16_emitpcode(POC_BSF,
9960 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
9962 pic16_emitpcode(POC_BCF,
9963 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
9968 pic16_emitpcode(POC_BSF,
9969 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9971 pic16_emitpcode(POC_BCF,
9972 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9979 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9982 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9984 /* if the bit lenth is less than or */
9985 /* it exactly fits a byte then */
9986 if((shCnt=SPEC_BSTR(etype))
9987 || SPEC_BLEN(etype) <= 8 ) {
9989 /* shift left acc */
9992 /* using PRODL as a temporary register here */
9993 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9999 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10000 // pic16_emitcode ("mov","b,a");
10001 // pic16_emitcode("mov","a,@%s",rname);
10005 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10006 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
10007 (unsigned char)(0xff >> (8-bstr))) ));
10008 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
10009 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10016 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10017 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10022 if ( SPEC_BLEN(etype) <= 8 )
10025 pic16_emitcode("inc","%s",rname);
10026 rLen = SPEC_BLEN(etype) ;
10030 /* now generate for lengths greater than one byte */
10033 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
10043 pic16_emitcode("mov","@%s,a",rname);
10045 pic16_emitcode("mov","@%s,%s",rname,l);
10050 pic16_emitcode("movx","@dptr,a");
10055 DEBUGpic16_emitcode(";lcall","__gptrput");
10058 pic16_emitcode ("inc","%s",rname);
10063 /* last last was not complete */
10065 /* save the byte & read byte */
10068 pic16_emitcode ("mov","b,a");
10069 pic16_emitcode("mov","a,@%s",rname);
10073 pic16_emitcode ("mov","b,a");
10074 pic16_emitcode("movx","a,@dptr");
10078 pic16_emitcode ("push","b");
10079 pic16_emitcode ("push","acc");
10080 pic16_emitcode ("lcall","__gptrget");
10081 pic16_emitcode ("pop","b");
10085 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
10086 pic16_emitcode ("orl","a,b");
10089 if (p_type == GPOINTER)
10090 pic16_emitcode("pop","b");
10095 pic16_emitcode("mov","@%s,a",rname);
10099 pic16_emitcode("movx","@dptr,a");
10103 DEBUGpic16_emitcode(";lcall","__gptrput");
10107 /*-----------------------------------------------------------------*/
10108 /* genDataPointerSet - remat pointer to data space */
10109 /*-----------------------------------------------------------------*/
10110 static void genDataPointerSet(operand *right,
10114 int size, offset = 0, resoffset=0 ;
10116 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10117 pic16_aopOp(right,ic,FALSE);
10119 size = AOP_SIZE(right);
10121 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10124 if ( AOP_TYPE(result) == AOP_PCODE) {
10125 fprintf(stderr,"genDataPointerSet %s, %d\n",
10126 AOP(result)->aopu.pcop->name,
10127 (AOP(result)->aopu.pcop->type == PO_DIR)?
10128 PCOR(AOP(result)->aopu.pcop)->instance:
10129 PCOI(AOP(result)->aopu.pcop)->offset);
10133 if(AOP(result)->aopu.pcop->type == PO_DIR)
10134 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
10137 if (AOP_TYPE(right) == AOP_LIT) {
10138 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
10140 lit = lit >> (8*offset);
10142 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
10143 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
10145 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
10148 mov2w(AOP(right), offset);
10149 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
10155 pic16_freeAsmop(right,NULL,ic,TRUE);
10160 /*-----------------------------------------------------------------*/
10161 /* genNearPointerSet - pic16_emitcode for near pointer put */
10162 /*-----------------------------------------------------------------*/
10163 static void genNearPointerSet (operand *right,
10170 sym_link *ptype = operandType(result);
10171 sym_link *resetype;
10173 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10174 retype= getSpec(operandType(right));
10175 resetype = getSpec(operandType(result));
10177 pic16_aopOp(result,ic,FALSE);
10179 /* if the result is rematerializable &
10180 * in data space & not a bit variable */
10182 /* and result is not a bit variable */
10183 if (AOP_TYPE(result) == AOP_PCODE
10184 // && AOP_TYPE(result) == AOP_IMMD
10185 && DCL_TYPE(ptype) == POINTER
10186 && !IS_BITFIELD(retype)
10187 && !IS_BITFIELD(resetype)) {
10189 genDataPointerSet (right,result,ic);
10190 pic16_freeAsmop(result,NULL,ic,TRUE);
10194 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10195 pic16_aopOp(right,ic,FALSE);
10196 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10198 /* if the value is already in a pointer register
10199 * then don't need anything more */
10200 if (!AOP_INPREG(AOP(result))) {
10201 /* otherwise get a free pointer register */
10202 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10204 if( (AOP_TYPE(result) == AOP_PCODE)
10205 && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10206 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10208 if(!IS_BITFIELD(resetype))
10209 pic16_loadFSR0( result ); // patch 10
10211 // set up FSR0 with address of result
10212 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10213 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10218 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10220 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10222 /* if bitfield then unpack the bits */
10223 if (IS_BITFIELD(resetype)) {
10224 genPackBits (resetype, result, right, NULL, POINTER);
10226 /* we have can just get the values */
10227 int size = AOP_SIZE(right);
10230 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10232 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10235 //pic16_emitcode("mov","@%s,a",rname);
10236 pic16_emitcode("movf","indf0,w ;1");
10239 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
10240 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
10242 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
10244 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
10246 } else { // no literal //
10248 pic16_emitpcode(POC_MOVFF, //
10249 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10250 pic16_popCopyReg(&pic16_pc_postinc0))); //
10252 pic16_emitpcode(POC_MOVFF, //
10253 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10254 pic16_popCopyReg(&pic16_pc_indf0))); //
10262 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10263 /* now some housekeeping stuff */
10265 /* we had to allocate for this iCode */
10266 pic16_freeAsmop(NULL,aop,ic,TRUE);
10268 /* we did not allocate which means left
10269 * already in a pointer register, then
10270 * if size > 0 && this could be used again
10271 * we have to point it back to where it
10273 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10274 if (AOP_SIZE(right) > 1
10275 && !OP_SYMBOL(result)->remat
10276 && ( OP_SYMBOL(result)->liveTo > ic->seq
10279 int size = AOP_SIZE(right) - 1;
10282 pic16_emitcode("decf","fsr0,f");
10283 //pic16_emitcode("dec","%s",rname);
10287 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10290 pic16_freeAsmop(right,NULL,ic,TRUE);
10291 pic16_freeAsmop(result,NULL,ic,TRUE);
10294 /*-----------------------------------------------------------------*/
10295 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
10296 /*-----------------------------------------------------------------*/
10297 static void genPagedPointerSet (operand *right,
10302 regs *preg = NULL ;
10306 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10308 retype= getSpec(operandType(right));
10310 pic16_aopOp(result,ic,FALSE);
10312 /* if the value is already in a pointer register
10313 then don't need anything more */
10314 if (!AOP_INPREG(AOP(result))) {
10315 /* otherwise get a free pointer register */
10317 preg = getFreePtr(ic,&aop,FALSE);
10318 pic16_emitcode("mov","%s,%s",
10320 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10321 rname = preg->name ;
10323 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10325 pic16_freeAsmop(result,NULL,ic,TRUE);
10326 pic16_aopOp (right,ic,FALSE);
10328 /* if bitfield then unpack the bits */
10329 if (IS_BITFIELD(retype))
10330 genPackBits (retype,result,right,rname,PPOINTER);
10332 /* we have can just get the values */
10333 int size = AOP_SIZE(right);
10337 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10340 pic16_emitcode("movx","@%s,a",rname);
10343 pic16_emitcode("inc","%s",rname);
10349 /* now some housekeeping stuff */
10351 /* we had to allocate for this iCode */
10352 pic16_freeAsmop(NULL,aop,ic,TRUE);
10354 /* we did not allocate which means left
10355 already in a pointer register, then
10356 if size > 0 && this could be used again
10357 we have to point it back to where it
10359 if (AOP_SIZE(right) > 1 &&
10360 !OP_SYMBOL(result)->remat &&
10361 ( OP_SYMBOL(result)->liveTo > ic->seq ||
10363 int size = AOP_SIZE(right) - 1;
10365 pic16_emitcode("dec","%s",rname);
10370 pic16_freeAsmop(right,NULL,ic,TRUE);
10375 /*-----------------------------------------------------------------*/
10376 /* genFarPointerSet - set value from far space */
10377 /*-----------------------------------------------------------------*/
10378 static void genFarPointerSet (operand *right,
10379 operand *result, iCode *ic)
10382 sym_link *retype = getSpec(operandType(right));
10384 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10385 pic16_aopOp(result,ic,FALSE);
10387 /* if the operand is already in dptr
10388 then we do nothing else we move the value to dptr */
10389 if (AOP_TYPE(result) != AOP_STR) {
10390 /* if this is remateriazable */
10391 if (AOP_TYPE(result) == AOP_IMMD)
10392 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10393 else { /* we need to get it byte by byte */
10394 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10395 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10396 if (options.model == MODEL_FLAT24)
10398 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10402 /* so dptr know contains the address */
10403 pic16_freeAsmop(result,NULL,ic,TRUE);
10404 pic16_aopOp(right,ic,FALSE);
10406 /* if bit then unpack */
10407 if (IS_BITFIELD(retype))
10408 genPackBits(retype,result,right,"dptr",FPOINTER);
10410 size = AOP_SIZE(right);
10414 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10416 pic16_emitcode("movx","@dptr,a");
10418 pic16_emitcode("inc","dptr");
10422 pic16_freeAsmop(right,NULL,ic,TRUE);
10425 /*-----------------------------------------------------------------*/
10426 /* genGenPointerSet - set value from generic pointer space */
10427 /*-----------------------------------------------------------------*/
10428 static void genGenPointerSet (operand *right,
10429 operand *result, iCode *ic)
10431 int i, size, offset, lit;
10432 sym_link *retype = getSpec(operandType(right));
10434 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10436 pic16_aopOp(result,ic,FALSE);
10437 pic16_aopOp(right,ic,FALSE);
10438 size = AOP_SIZE(right);
10441 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10443 /* if the operand is already in dptr
10444 then we do nothing else we move the value to dptr */
10445 if (AOP_TYPE(result) != AOP_STR) {
10446 /* if this is remateriazable */
10447 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10448 // WARNING: anythig until "else" is untested!
10449 if (AOP_TYPE(result) == AOP_IMMD) {
10450 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10451 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10452 // load FSR0 from immediate
10453 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10457 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10459 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10465 else { /* we need to get it byte by byte */
10466 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10467 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10469 // set up FSR0 with address of result
10470 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10471 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10473 /* hack hack! see if this the FSR. If so don't load W */
10474 if(AOP_TYPE(right) != AOP_ACC) {
10476 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10478 if(AOP_TYPE(right) == AOP_LIT)
10481 // note: pic16_popGet handles sign extension
10482 for(i=0;i<size;i++) {
10483 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10485 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10487 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10492 for(i=0;i<size;i++) {
10494 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10495 pic16_popCopyReg(&pic16_pc_postinc0)));
10497 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10498 pic16_popCopyReg(&pic16_pc_indf0)));
10504 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10505 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10507 } // if (AOP_TYPE(result) != AOP_IMMD)
10509 } // if (AOP_TYPE(result) != AOP_STR)
10510 /* so dptr know contains the address */
10513 /* if bit then unpack */
10514 if (IS_BITFIELD(retype))
10515 genPackBits(retype,result,right,"dptr",GPOINTER);
10517 size = AOP_SIZE(right);
10520 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
10522 // set up FSR0 with address of result
10523 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10524 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10527 if (AOP_TYPE(right) == AOP_LIT) {
10528 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10530 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10532 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10534 } else { // no literal
10536 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10538 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10546 pic16_freeAsmop(right,NULL,ic,TRUE);
10547 pic16_freeAsmop(result,NULL,ic,TRUE);
10550 /*-----------------------------------------------------------------*/
10551 /* genPointerSet - stores the value into a pointer location */
10552 /*-----------------------------------------------------------------*/
10553 static void genPointerSet (iCode *ic)
10555 operand *right, *result ;
10556 sym_link *type, *etype;
10559 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10561 right = IC_RIGHT(ic);
10562 result = IC_RESULT(ic) ;
10564 /* depending on the type of pointer we need to
10565 move it to the correct pointer register */
10566 type = operandType(result);
10567 etype = getSpec(type);
10568 /* if left is of type of pointer then it is simple */
10569 if (IS_PTR(type) && !IS_FUNC(type->next)) {
10570 p_type = DCL_TYPE(type);
10573 /* we have to go by the storage class */
10574 p_type = PTR_TYPE(SPEC_OCLS(etype));
10576 /* if (SPEC_OCLS(etype)->codesp ) { */
10577 /* p_type = CPOINTER ; */
10580 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10581 /* p_type = FPOINTER ; */
10583 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10584 /* p_type = PPOINTER ; */
10586 /* if (SPEC_OCLS(etype) == idata ) */
10587 /* p_type = IPOINTER ; */
10589 /* p_type = POINTER ; */
10592 /* now that we have the pointer type we assign
10593 the pointer values */
10598 genNearPointerSet (right,result,ic);
10602 genPagedPointerSet (right,result,ic);
10606 genFarPointerSet (right,result,ic);
10610 genGenPointerSet (right,result,ic);
10614 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10615 "genPointerSet: illegal pointer type");
10619 /*-----------------------------------------------------------------*/
10620 /* genIfx - generate code for Ifx statement */
10621 /*-----------------------------------------------------------------*/
10622 static void genIfx (iCode *ic, iCode *popIc)
10624 operand *cond = IC_COND(ic);
10627 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10629 pic16_aopOp(cond,ic,FALSE);
10631 /* get the value into acc */
10632 if (AOP_TYPE(cond) != AOP_CRY)
10633 pic16_toBoolean(cond);
10636 /* the result is now in the accumulator */
10637 pic16_freeAsmop(cond,NULL,ic,TRUE);
10639 /* if there was something to be popped then do it */
10643 /* if the condition is a bit variable */
10644 if (isbit && IS_ITEMP(cond) &&
10646 genIfxJump(ic,SPIL_LOC(cond)->rname);
10647 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10650 if (isbit && !IS_ITEMP(cond))
10651 genIfxJump(ic,OP_SYMBOL(cond)->rname);
10653 genIfxJump(ic,"a");
10659 /*-----------------------------------------------------------------*/
10660 /* genAddrOf - generates code for address of */
10661 /*-----------------------------------------------------------------*/
10662 static void genAddrOf (iCode *ic)
10664 operand *result, *left;
10666 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
10667 pCodeOp *pcop0, *pcop1, *pcop2;
10669 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10671 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10672 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10674 sym = OP_SYMBOL( left );
10676 size = AOP_SIZE(IC_RESULT(ic));
10680 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
10685 // if(pic16_debug_verbose) {
10686 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10687 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10690 /* Assume that what we want the address of is in data space
10691 * since there is no stack on the PIC, yet! -- VR */
10693 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10696 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10699 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10703 pic16_emitpcode(POC_MOVLW, pcop0);
10704 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10705 pic16_emitpcode(POC_MOVLW, pcop1);
10706 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10707 pic16_emitpcode(POC_MOVLW, pcop2);
10708 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10711 pic16_emitpcode(POC_MOVLW, pcop0);
10712 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10713 pic16_emitpcode(POC_MOVLW, pcop1);
10714 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10716 pic16_emitpcode(POC_MOVLW, pcop0);
10717 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10720 pic16_freeAsmop(result,NULL,ic,TRUE);
10721 pic16_freeAsmop(left, NULL, ic, FALSE);
10726 /*-----------------------------------------------------------------*/
10727 /* genFarFarAssign - assignment when both are in far space */
10728 /*-----------------------------------------------------------------*/
10729 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10731 int size = AOP_SIZE(right);
10734 /* first push the right side on to the stack */
10736 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10738 pic16_emitcode ("push","acc");
10741 pic16_freeAsmop(right,NULL,ic,FALSE);
10742 /* now assign DPTR to result */
10743 pic16_aopOp(result,ic,FALSE);
10744 size = AOP_SIZE(result);
10746 pic16_emitcode ("pop","acc");
10747 pic16_aopPut(AOP(result),"a",--offset);
10749 pic16_freeAsmop(result,NULL,ic,FALSE);
10754 /*-----------------------------------------------------------------*/
10755 /* genAssign - generate code for assignment */
10756 /*-----------------------------------------------------------------*/
10757 static void genAssign (iCode *ic)
10759 operand *result, *right;
10760 int size, offset,know_W;
10761 unsigned long lit = 0L;
10763 result = IC_RESULT(ic);
10764 right = IC_RIGHT(ic) ;
10766 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10768 /* if they are the same */
10769 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10772 pic16_aopOp(right,ic,FALSE);
10773 pic16_aopOp(result,ic,TRUE);
10775 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10777 /* if they are the same registers */
10778 if (pic16_sameRegs(AOP(right),AOP(result)))
10781 /* if the result is a bit */
10782 if (AOP_TYPE(result) == AOP_CRY) {
10783 /* if the right size is a literal then
10784 we know what the value is */
10785 if (AOP_TYPE(right) == AOP_LIT) {
10787 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10788 pic16_popGet(AOP(result),0));
10790 if (((int) operandLitValue(right)))
10791 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10792 AOP(result)->aopu.aop_dir,
10793 AOP(result)->aopu.aop_dir);
10795 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10796 AOP(result)->aopu.aop_dir,
10797 AOP(result)->aopu.aop_dir);
10801 /* the right is also a bit variable */
10802 if (AOP_TYPE(right) == AOP_CRY) {
10803 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10804 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10805 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10807 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10808 AOP(result)->aopu.aop_dir,
10809 AOP(result)->aopu.aop_dir);
10810 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10811 AOP(right)->aopu.aop_dir,
10812 AOP(right)->aopu.aop_dir);
10813 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10814 AOP(result)->aopu.aop_dir,
10815 AOP(result)->aopu.aop_dir);
10819 /* we need to or */
10820 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10821 pic16_toBoolean(right);
10823 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10824 //pic16_aopPut(AOP(result),"a",0);
10828 /* bit variables done */
10830 size = AOP_SIZE(result);
10833 if(AOP_TYPE(right) == AOP_LIT) {
10834 if(!IS_FLOAT(operandType( right )))
10835 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10838 unsigned long lit_int;
10842 /* take care if literal is a float */
10843 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10844 lit = info.lit_int;
10848 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10849 // sizeof(unsigned long int), sizeof(float));
10851 if(AOP_TYPE(right) != AOP_LIT
10852 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10853 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10854 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
10856 // set up table pointer
10857 if( (AOP_TYPE(right) == AOP_PCODE)
10858 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10859 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10861 fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
10862 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10863 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10864 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10865 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10866 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10867 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10869 fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
10870 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10871 pic16_popCopyReg(&pic16_pc_tblptrl)));
10872 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10873 pic16_popCopyReg(&pic16_pc_tblptrh)));
10874 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10875 pic16_popCopyReg(&pic16_pc_tblptru)));
10878 size = min(AOP_SIZE(right), AOP_SIZE(result));
10880 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10881 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10882 pic16_popGet(AOP(result),offset)));
10886 if(AOP_SIZE(result) > AOP_SIZE(right)) {
10887 size = AOP_SIZE(result) - AOP_SIZE(right);
10889 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10898 /* VR - What is this?! */
10899 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10900 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10901 if(aopIdx(AOP(result),0) == 4) {
10902 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10904 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10905 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10909 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10914 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10915 if(AOP_TYPE(right) == AOP_LIT) {
10917 if(know_W != (lit&0xff))
10918 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10920 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10922 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10926 } else if (AOP_TYPE(right) == AOP_CRY) {
10927 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10929 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10930 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10932 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10933 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10934 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10936 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10939 /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10940 normally should work, but mind that the W register live range
10941 is not checked, so if the code generator assumes that the W
10942 is already loaded after such a pair, wrong code will be generated.
10944 Checking the live range is the next step.
10945 This is experimental code yet and has not been fully tested yet.
10946 USE WITH CARE. Revert to old code by setting 0 to the condition above.
10947 Vangelis Rokas 030603 (vrokas@otenet.gr) */
10949 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10951 /* This is the old code, which is assumed(?!) that works fine(!?) */
10953 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10954 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10963 pic16_freeAsmop (right,NULL,ic,FALSE);
10964 pic16_freeAsmop (result,NULL,ic,TRUE);
10967 /*-----------------------------------------------------------------*/
10968 /* genJumpTab - generates code for jump table */
10969 /*-----------------------------------------------------------------*/
10970 static void genJumpTab (iCode *ic)
10975 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10977 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10978 /* get the condition into accumulator */
10979 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10981 /* multiply by three */
10982 pic16_emitcode("add","a,acc");
10983 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10985 jtab = newiTempLabel(NULL);
10986 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10987 pic16_emitcode("jmp","@a+dptr");
10988 pic16_emitcode("","%05d_DS_:",jtab->key+100);
10990 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10991 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10993 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10994 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10995 pic16_emitpLabel(jtab->key);
10997 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10999 /* now generate the jump labels */
11000 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
11001 jtab = setNextItem(IC_JTLABELS(ic))) {
11002 pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
11003 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
11009 /*-----------------------------------------------------------------*/
11010 /* genMixedOperation - gen code for operators between mixed types */
11011 /*-----------------------------------------------------------------*/
11013 TSD - Written for the PIC port - but this unfortunately is buggy.
11014 This routine is good in that it is able to efficiently promote
11015 types to different (larger) sizes. Unfortunately, the temporary
11016 variables that are optimized out by this routine are sometimes
11017 used in other places. So until I know how to really parse the
11018 iCode tree, I'm going to not be using this routine :(.
11020 static int genMixedOperation (iCode *ic)
11023 operand *result = IC_RESULT(ic);
11024 sym_link *ctype = operandType(IC_LEFT(ic));
11025 operand *right = IC_RIGHT(ic);
11031 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
11033 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11039 nextright = IC_RIGHT(nextic);
11040 nextleft = IC_LEFT(nextic);
11041 nextresult = IC_RESULT(nextic);
11043 pic16_aopOp(right,ic,FALSE);
11044 pic16_aopOp(result,ic,FALSE);
11045 pic16_aopOp(nextright, nextic, FALSE);
11046 pic16_aopOp(nextleft, nextic, FALSE);
11047 pic16_aopOp(nextresult, nextic, FALSE);
11049 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
11051 operand *t = right;
11055 pic16_emitcode(";remove right +","");
11057 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
11059 operand *t = right;
11063 pic16_emitcode(";remove left +","");
11067 big = AOP_SIZE(nextleft);
11068 small = AOP_SIZE(nextright);
11070 switch(nextic->op) {
11073 pic16_emitcode(";optimize a +","");
11074 /* if unsigned or not an integral type */
11075 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
11076 pic16_emitcode(";add a bit to something","");
11079 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
11081 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
11082 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
11083 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
11085 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
11093 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11094 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11095 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11098 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11100 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11101 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
11102 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
11103 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11104 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
11107 pic16_emitcode("rlf","known_zero,w");
11114 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11115 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11116 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11118 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11128 pic16_freeAsmop(right,NULL,ic,TRUE);
11129 pic16_freeAsmop(result,NULL,ic,TRUE);
11130 pic16_freeAsmop(nextright,NULL,ic,TRUE);
11131 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
11133 nextic->generated = 1;
11140 /*-----------------------------------------------------------------*/
11141 /* genCast - gen code for casting */
11142 /*-----------------------------------------------------------------*/
11143 static void genCast (iCode *ic)
11145 operand *result = IC_RESULT(ic);
11146 sym_link *ctype = operandType(IC_LEFT(ic));
11147 sym_link *rtype = operandType(IC_RIGHT(ic));
11148 operand *right = IC_RIGHT(ic);
11151 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11152 /* if they are equivalent then do nothing */
11153 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
11156 pic16_aopOp(right,ic,FALSE) ;
11157 pic16_aopOp(result,ic,FALSE);
11159 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11161 /* if the result is a bit */
11162 if (AOP_TYPE(result) == AOP_CRY) {
11164 /* if the right size is a literal then
11165 * we know what the value is */
11166 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11168 if (AOP_TYPE(right) == AOP_LIT) {
11169 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11170 pic16_popGet(AOP(result),0));
11172 if (((int) operandLitValue(right)))
11173 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
11174 AOP(result)->aopu.aop_dir,
11175 AOP(result)->aopu.aop_dir);
11177 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
11178 AOP(result)->aopu.aop_dir,
11179 AOP(result)->aopu.aop_dir);
11183 /* the right is also a bit variable */
11184 if (AOP_TYPE(right) == AOP_CRY) {
11186 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11188 pic16_emitcode("clrc","");
11189 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11190 AOP(right)->aopu.aop_dir,
11191 AOP(right)->aopu.aop_dir);
11192 pic16_aopPut(AOP(result),"c",0);
11196 /* we need to or */
11197 if (AOP_TYPE(right) == AOP_REG) {
11198 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
11199 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
11200 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
11202 pic16_toBoolean(right);
11203 pic16_aopPut(AOP(result),"a",0);
11207 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11210 size = AOP_SIZE(result);
11212 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11214 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
11215 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11216 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
11219 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11224 /* if they are the same size : or less */
11225 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11227 /* if they are in the same place */
11228 if (pic16_sameRegs(AOP(right),AOP(result)))
11231 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11233 if (IS_PTR_CONST(rtype))
11235 if (IS_CODEPTR(rtype))
11237 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11240 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11242 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11244 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11247 if(AOP_TYPE(right) == AOP_IMMD) {
11248 pCodeOp *pcop0, *pcop1, *pcop2;
11249 symbol *sym = OP_SYMBOL( right );
11251 size = AOP_SIZE(result);
11253 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11255 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11257 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11260 pic16_emitpcode(POC_MOVLW, pcop0);
11261 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11262 pic16_emitpcode(POC_MOVLW, pcop1);
11263 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11264 pic16_emitpcode(POC_MOVLW, pcop2);
11265 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11268 pic16_emitpcode(POC_MOVLW, pcop0);
11269 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11270 pic16_emitpcode(POC_MOVLW, pcop1);
11271 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11273 pic16_emitpcode(POC_MOVLW, pcop0);
11274 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11278 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11279 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11280 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11281 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11282 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11283 if(AOP_SIZE(result) <2)
11284 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11286 /* if they in different places then copy */
11287 size = AOP_SIZE(result);
11290 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11291 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11298 /* if the result is of type pointer */
11299 if (IS_PTR(ctype)) {
11301 sym_link *type = operandType(right);
11302 sym_link *etype = getSpec(type);
11304 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
11306 /* pointer to generic pointer */
11307 if (IS_GENPTR(ctype)) {
11311 p_type = DCL_TYPE(type);
11313 /* we have to go by the storage class */
11314 p_type = PTR_TYPE(SPEC_OCLS(etype));
11316 /* if (SPEC_OCLS(etype)->codesp ) */
11317 /* p_type = CPOINTER ; */
11319 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11320 /* p_type = FPOINTER ; */
11322 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11323 /* p_type = PPOINTER; */
11325 /* if (SPEC_OCLS(etype) == idata ) */
11326 /* p_type = IPOINTER ; */
11328 /* p_type = POINTER ; */
11331 /* the first two bytes are known */
11332 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
11333 size = GPTRSIZE - 1;
11336 if(offset < AOP_SIZE(right)) {
11337 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
11338 if ((AOP_TYPE(right) == AOP_PCODE) &&
11339 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11340 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11341 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11343 pic16_aopPut(AOP(result),
11344 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11348 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11351 /* the last byte depending on type */
11355 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11358 pic16_emitcode(";BUG!? ","%d",__LINE__);
11362 pic16_emitcode(";BUG!? ","%d",__LINE__);
11366 pic16_emitcode(";BUG!? ","%d",__LINE__);
11371 /* this should never happen */
11372 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11373 "got unknown pointer type");
11376 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
11380 /* just copy the pointers */
11381 size = AOP_SIZE(result);
11384 pic16_aopPut(AOP(result),
11385 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11394 /* so we now know that the size of destination is greater
11395 than the size of the source.
11396 Now, if the next iCode is an operator then we might be
11397 able to optimize the operation without performing a cast.
11399 if(genMixedOperation(ic))
11402 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11404 /* we move to result for the size of source */
11405 size = AOP_SIZE(right);
11408 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11409 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11410 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11414 /* now depending on the sign of the destination */
11415 size = AOP_SIZE(result) - AOP_SIZE(right);
11416 /* if unsigned or not an integral type */
11417 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11419 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11421 /* we need to extend the sign :( */
11424 /* Save one instruction of casting char to int */
11425 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11426 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11427 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
11429 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11432 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11434 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11436 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
11439 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
11444 pic16_freeAsmop(right,NULL,ic,TRUE);
11445 pic16_freeAsmop(result,NULL,ic,TRUE);
11449 /*-----------------------------------------------------------------*/
11450 /* genDjnz - generate decrement & jump if not zero instrucion */
11451 /*-----------------------------------------------------------------*/
11452 static int genDjnz (iCode *ic, iCode *ifx)
11454 symbol *lbl, *lbl1;
11455 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11460 /* if the if condition has a false label
11461 then we cannot save */
11465 /* if the minus is not of the form
11467 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11468 !IS_OP_LITERAL(IC_RIGHT(ic)))
11471 if (operandLitValue(IC_RIGHT(ic)) != 1)
11474 /* if the size of this greater than one then no
11476 if (getSize(operandType(IC_RESULT(ic))) > 1)
11479 /* otherwise we can save BIG */
11480 lbl = newiTempLabel(NULL);
11481 lbl1= newiTempLabel(NULL);
11483 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11485 if (IS_AOP_PREG(IC_RESULT(ic))) {
11486 pic16_emitcode("dec","%s",
11487 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11488 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11489 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11493 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11494 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11496 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11497 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
11500 /* pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11501 /* pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11502 /* pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11503 /* pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11506 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11507 ifx->generated = 1;
11511 /*-----------------------------------------------------------------*/
11512 /* genReceive - generate code for a receive iCode */
11513 /*-----------------------------------------------------------------*/
11514 static void genReceive (iCode *ic)
11516 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11519 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11520 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
11522 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11524 if (isOperandInFarSpace(IC_RESULT(ic)) &&
11525 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11526 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11528 int size = getSize(operandType(IC_RESULT(ic)));
11529 int offset = pic16_fReturnSizePic - size;
11533 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11534 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11538 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
11540 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11541 size = AOP_SIZE(IC_RESULT(ic));
11544 pic16_emitcode ("pop","acc");
11545 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11548 DEBUGpic16_emitcode ("; ***","2 %s %d",__FUNCTION__,__LINE__);
11551 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11553 assignResultValue(IC_RESULT(ic), 0);
11556 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11559 /*-----------------------------------------------------------------*/
11560 /* genDummyRead - generate code for dummy read of volatiles */
11561 /*-----------------------------------------------------------------*/
11563 genDummyRead (iCode * ic)
11565 pic16_emitcode ("; genDummyRead","");
11566 pic16_emitcode ("; not implemented","");
11571 /*-----------------------------------------------------------------*/
11572 /* genpic16Code - generate code for pic16 based controllers */
11573 /*-----------------------------------------------------------------*/
11575 * At this point, ralloc.c has gone through the iCode and attempted
11576 * to optimize in a way suitable for a PIC. Now we've got to generate
11577 * PIC instructions that correspond to the iCode.
11579 * Once the instructions are generated, we'll pass through both the
11580 * peep hole optimizer and the pCode optimizer.
11581 *-----------------------------------------------------------------*/
11583 void genpic16Code (iCode *lic)
11588 lineHead = lineCurr = NULL;
11590 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11591 pic16_addpBlock(pb);
11594 /* if debug information required */
11595 if (options.debug && currFunc) {
11597 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11602 for (ic = lic ; ic ; ic = ic->next ) {
11604 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11605 if ( cln != ic->lineno ) {
11606 if ( options.debug ) {
11607 debugFile->writeCLine (ic);
11610 if(!options.noCcodeInAsm) {
11611 pic16_addpCode2pBlock(pb,
11612 pic16_newpCodeCSource(ic->lineno, ic->filename,
11613 printCLine(ic->filename, ic->lineno)));
11619 if(options.iCodeInAsm) {
11621 /* insert here code to print iCode as comment */
11622 l = Safe_strdup(printILine(ic));
11623 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11626 /* if the result is marked as
11627 spilt and rematerializable or code for
11628 this has already been generated then
11630 if (resultRemat(ic) || ic->generated )
11633 /* depending on the operation */
11652 /* IPOP happens only when trying to restore a
11653 spilt live range, if there is an ifx statement
11654 following this pop then the if statement might
11655 be using some of the registers being popped which
11656 would destroy the contents of the register so
11657 we need to check for this condition and handle it */
11659 ic->next->op == IFX &&
11660 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
11661 genIfx (ic->next,ic);
11679 genEndFunction (ic);
11695 pic16_genPlus (ic) ;
11699 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11700 pic16_genMinus (ic);
11716 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
11720 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11727 /* note these two are xlated by algebraic equivalence
11728 during parsing SDCC.y */
11729 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11730 "got '>=' or '<=' shouldn't have come here");
11734 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11746 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11750 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11754 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11778 genRightShift (ic);
11781 case GET_VALUE_AT_ADDRESS:
11786 if (POINTER_SET(ic))
11813 addSet(&_G.sendSet,ic);
11816 case DUMMY_READ_VOLATILE:
11826 /* now we are ready to call the
11827 peep hole optimizer */
11828 if (!options.nopeep) {
11829 peepHole (&lineHead);
11831 /* now do the actual printing */
11832 printLine (lineHead,codeOutFile);
11835 DFPRINTF((stderr,"printing pBlock\n\n"));
11836 pic16_printpBlock(stdout,pb);