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;
137 /* Resolved ifx structure. This structure stores information
138 about an iCode ifx that makes it easier to generate code.
140 typedef struct resolvedIfx {
141 symbol *lbl; /* pointer to a label */
142 int condition; /* true or false ifx */
143 int generated; /* set true when the code associated with the ifx
147 extern int pic16_ptrRegReq ;
148 extern int pic16_nRegs;
149 extern FILE *codeOutFile;
150 static void saverbank (int, iCode *,bool);
152 static lineNode *lineHead = NULL;
153 static lineNode *lineCurr = NULL;
155 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
156 0xE0, 0xC0, 0x80, 0x00};
157 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
158 0x07, 0x03, 0x01, 0x00};
162 /*-----------------------------------------------------------------*/
163 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
164 /* exponent of 2 is returned, otherwise -1 is */
166 /* note that this is similar to the function `powof2' in SDCCsymt */
170 /*-----------------------------------------------------------------*/
171 static int my_powof2 (unsigned long num)
174 if( (num & (num-1)) == 0) {
187 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
189 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
191 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
192 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
193 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
194 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
195 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
196 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
197 ((result) ? AOP_SIZE(result) : 0));
200 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
203 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
205 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
206 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
207 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
208 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
209 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
210 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
214 void pic16_emitpcomment (char *fmt, ...)
217 char lb[INITIAL_INLINEASM];
223 vsprintf(lb+1,fmt,ap);
225 while (isspace(*lbp)) lbp++;
228 lineCurr = (lineCurr ?
229 connectLine(lineCurr,newLineNode(lb)) :
230 (lineHead = newLineNode(lb)));
231 lineCurr->isInline = _G.inLine;
232 lineCurr->isDebug = _G.debugLine;
234 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
237 // fprintf(stderr, "%s\n", lb);
240 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
243 char lb[INITIAL_INLINEASM];
246 if(!pic16_debug_verbose)
253 sprintf(lb,"%s\t",inst);
255 sprintf(lb,"%s",inst);
256 vsprintf(lb+(strlen(lb)),fmt,ap);
260 while (isspace(*lbp)) lbp++;
263 lineCurr = (lineCurr ?
264 connectLine(lineCurr,newLineNode(lb)) :
265 (lineHead = newLineNode(lb)));
266 lineCurr->isInline = _G.inLine;
267 lineCurr->isDebug = _G.debugLine;
269 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
272 // fprintf(stderr, "%s\n", lb);
275 void pic16_emitpLabel(int key)
277 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
280 void pic16_emitpLabelFORCE(int key)
282 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
285 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
289 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
291 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
293 // fprintf(stderr, "%s\n", pcop->name);
296 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
299 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
305 #define pic16_emitcode DEBUGpic16_emitcode
307 /*-----------------------------------------------------------------*/
308 /* pic16_emitcode - writes the code into a file : for now it is simple */
309 /*-----------------------------------------------------------------*/
310 void pic16_emitcode (char *inst,char *fmt, ...)
313 char lb[INITIAL_INLINEASM];
320 sprintf(lb,"%s\t",inst);
322 sprintf(lb,"%s",inst);
323 vsprintf(lb+(strlen(lb)),fmt,ap);
327 while (isspace(*lbp)) lbp++;
330 lineCurr = (lineCurr ?
331 connectLine(lineCurr,newLineNode(lb)) :
332 (lineHead = newLineNode(lb)));
333 lineCurr->isInline = _G.inLine;
334 lineCurr->isDebug = _G.debugLine;
336 // VR fprintf(stderr, "lb = <%s>\n", lbp);
338 // if(pic16_debug_verbose)
339 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
346 /*-----------------------------------------------------------------*/
347 /* pic16_emitDebuggerSymbol - associate the current code location */
348 /* with a debugger symbol */
349 /*-----------------------------------------------------------------*/
351 pic16_emitDebuggerSymbol (char * debugSym)
354 pic16_emitcode (";", "%s ==.", debugSym);
359 /*-----------------------------------------------------------------*/
360 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
361 /*-----------------------------------------------------------------*/
362 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
364 // bool r0iu = FALSE , r1iu = FALSE;
365 // bool r0ou = FALSE , r1ou = FALSE;
366 bool fsr0iu = FALSE, fsr0ou;
367 bool fsr2iu = FALSE, fsr2ou;
369 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
372 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
373 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
375 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
376 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
378 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
379 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
380 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
383 /* no usage of FSR2 */
384 if(!fsr2iu && !fsr2ou) {
385 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
386 (*aopp)->type = AOP_FSR2;
388 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
391 if(!fsr0iu && !fsr0ou) {
392 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
393 (*aopp)->type = AOP_FSR0;
395 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
398 /* now we know they both have usage */
399 /* if fsr0 not used in this instruction */
401 if (!_G.fsr0Pushed) {
402 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
403 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
407 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
408 (*aopp)->type = AOP_FSR0;
410 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
414 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
418 /* the logic: if r0 & r1 used in the instruction
419 then we are in trouble otherwise */
421 /* first check if r0 & r1 are used by this
422 instruction, in which case we are in trouble */
423 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
424 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
429 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
430 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
432 /* if no usage of r0 then return it */
433 if (!r0iu && !r0ou) {
434 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
435 (*aopp)->type = AOP_R0;
437 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
440 /* if no usage of r1 then return it */
441 if (!r1iu && !r1ou) {
442 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
443 (*aopp)->type = AOP_R1;
445 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
448 /* now we know they both have usage */
449 /* if r0 not used in this instruction */
451 /* push it if not already pushed */
453 //pic16_emitcode ("push","%s",
454 // pic16_regWithIdx(R0_IDX)->dname);
458 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
459 (*aopp)->type = AOP_R0;
461 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
464 /* if r1 not used then */
467 /* push it if not already pushed */
469 //pic16_emitcode ("push","%s",
470 // pic16_regWithIdx(R1_IDX)->dname);
474 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
475 (*aopp)->type = AOP_R1;
476 return pic16_regWithIdx(R1_IDX);
480 /* I said end of world but not quite end of world yet */
481 /* if this is a result then we can push it on the stack*/
483 (*aopp)->type = AOP_STK;
487 /* other wise this is true end of the world */
488 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
489 "getFreePtr should never reach here");
494 /*-----------------------------------------------------------------*/
495 /* newAsmop - creates a new asmOp */
496 /*-----------------------------------------------------------------*/
497 static asmop *newAsmop (short type)
501 aop = Safe_calloc(1,sizeof(asmop));
506 static void genSetDPTR(int n)
510 pic16_emitcode(";", "Select standard DPTR");
511 pic16_emitcode("mov", "dps, #0x00");
515 pic16_emitcode(";", "Select alternate DPTR");
516 pic16_emitcode("mov", "dps, #0x01");
520 /*-----------------------------------------------------------------*/
521 /* resolveIfx - converts an iCode ifx into a form more useful for */
522 /* generating code */
523 /*-----------------------------------------------------------------*/
524 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
527 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
533 resIfx->condition = 1; /* assume that the ifx is true */
534 resIfx->generated = 0; /* indicate that the ifx has not been used */
537 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
540 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
541 __FUNCTION__,__LINE__,resIfx->lbl->key);
546 resIfx->lbl = IC_TRUE(ifx);
548 resIfx->lbl = IC_FALSE(ifx);
549 resIfx->condition = 0;
554 DEBUGpic16_emitcode("; ***","ifx true is non-null");
556 DEBUGpic16_emitcode("; ***","ifx false is non-null");
560 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
564 /*-----------------------------------------------------------------*/
565 /* pointerCode - returns the code for a pointer type */
566 /*-----------------------------------------------------------------*/
567 static int pointerCode (sym_link *etype)
570 return PTR_TYPE(SPEC_OCLS(etype));
575 /*-----------------------------------------------------------------*/
576 /* aopForSym - for a true symbol */
577 /*-----------------------------------------------------------------*/
578 static asmop *aopForSym (iCode *ic, operand *op, bool result)
580 symbol *sym=OP_SYMBOL(op);
582 memmap *space= SPEC_OCLS(sym->etype);
584 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
586 // sym = OP_SYMBOL(op);
588 /* if already has one */
590 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
594 /* if symbol was initially placed onStack then we must re-place it
595 * to direct memory, since pic16 does not have a specific stack */
597 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
602 /* assign depending on the storage class */
603 /* if it is on the stack or indirectly addressable */
604 /* space we need to assign either r0 or r1 to it */
605 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
607 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
608 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
610 sym->aop = aop = newAsmop(0);
611 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
612 aop->size = getSize(sym->type);
614 fprintf(stderr, "%s:%d\t%s\n", __FILE__, __LINE__, __FUNCTION__);
617 // sym->aop = aop = newAsmop (AOP_REG);
618 // aop->aopu.aop_dir = sym->name; //sym->rname ;
619 // aop->aopu.aop_reg[0] = pic16_regWithIdx(IDX_PLUSW0); //pic16_pc_plusw2.r;
620 // aop->size = getSize(sym->type);
621 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
624 // pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
627 // pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_fsr2l), pic16_popCopyReg(&pic16_pc_fsr0l)));
628 // pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_fsr2h), pic16_popCopyReg(&pic16_pc_fsr0h)));
631 /* initialise for stack access via frame pointer */
632 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
634 // pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
635 // pic16_popCopyReg(&pic16_pc_plusw2), pic16_popCopyReg(&pic16_pc_kzero)));
638 // pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
645 /* now assign the address of the variable to
646 the pointer register */
647 if (aop->type != AOP_STK) {
651 pic16_emitcode("push","acc");
653 pic16_emitcode("mov","a,_bp");
654 pic16_emitcode("add","a,#0x%02x",
656 ((char)(sym->stack - _G.nRegsSaved )) :
657 ((char)sym->stack)) & 0xff);
658 pic16_emitcode("mov","%s,a",
659 aop->aopu.aop_ptr->name);
662 pic16_emitcode("pop","acc");
664 pic16_emitcode("mov","%s,#%s",
665 aop->aopu.aop_ptr->name,
667 aop->paged = space->paged;
669 aop->aopu.aop_stk = sym->stack;
677 if (sym->onStack && options.stack10bit)
679 /* It's on the 10 bit stack, which is located in
683 //DEBUGpic16_emitcode(";","%d",__LINE__);
686 pic16_emitcode("push","acc");
688 pic16_emitcode("mov","a,_bp");
689 pic16_emitcode("add","a,#0x%02x",
691 ((char)(sym->stack - _G.nRegsSaved )) :
692 ((char)sym->stack)) & 0xff);
695 pic16_emitcode ("mov","dpx1,#0x40");
696 pic16_emitcode ("mov","dph1,#0x00");
697 pic16_emitcode ("mov","dpl1, a");
701 pic16_emitcode("pop","acc");
703 sym->aop = aop = newAsmop(AOP_DPTR2);
704 aop->size = getSize(sym->type);
708 //DEBUGpic16_emitcode(";","%d",__LINE__);
709 /* if in bit space */
710 if (IN_BITSPACE(space)) {
711 sym->aop = aop = newAsmop (AOP_CRY);
712 aop->aopu.aop_dir = sym->rname ;
713 aop->size = getSize(sym->type);
714 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
717 /* if it is in direct space */
718 if (IN_DIRSPACE(space)) {
719 sym->aop = aop = newAsmop (AOP_DIR);
720 aop->aopu.aop_dir = sym->rname ;
721 aop->size = getSize(sym->type);
722 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
723 pic16_allocDirReg( IC_LEFT(ic) );
727 if (IN_FARSPACE(space)) {
728 sym->aop = aop = newAsmop (AOP_DIR);
729 aop->aopu.aop_dir = sym->rname ;
730 aop->size = getSize(sym->type);
731 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
732 pic16_allocDirReg( IC_LEFT(ic) );
737 /* special case for a function */
738 if (IS_FUNC(sym->type)) {
739 sym->aop = aop = newAsmop(AOP_IMMD);
740 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
741 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
742 strcpy(aop->aopu.aop_immd,sym->rname);
743 aop->size = FPTRSIZE;
744 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
750 /* only remaining is far space */
751 /* in which case DPTR gets the address */
752 sym->aop = aop = newAsmop(AOP_PCODE);
754 /* change the next if to 1 to revert to good old immediate code */
755 if(IN_CODESPACE(space)) {
756 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
757 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
758 PCOI(aop->aopu.pcop)->index = 0;
760 /* try to allocate via direct register */
761 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
762 // aop->size = getSize( sym->type );
765 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
766 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
769 if(!pic16_allocDirReg (IC_LEFT(ic)))
773 if(IN_DIRSPACE( space ))
775 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
776 aop->size = FPTRSIZE;
777 else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
778 else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
783 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
785 /* if it is in code space */
786 if (IN_CODESPACE(space))
792 /*-----------------------------------------------------------------*/
793 /* aopForRemat - rematerialzes an object */
794 /*-----------------------------------------------------------------*/
795 static asmop *aopForRemat (operand *op) // x symbol *sym)
797 symbol *sym = OP_SYMBOL(op);
798 iCode *ic = NULL, *oldic;
799 asmop *aop = newAsmop(AOP_PCODE);
805 ic = sym->rematiCode;
807 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
809 if(IS_OP_POINTER(op)) {
810 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
816 // pic16_emitpcomment("ic: %s\n", printILine(ic));
819 val += (int) operandLitValue(IC_RIGHT(ic));
820 } else if (ic->op == '-') {
821 val -= (int) operandLitValue(IC_RIGHT(ic));
825 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
828 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
830 if(!op->isaddr)viaimmd++; else viaimmd=0;
832 /* set the following if to 1 to revert to good old immediate code */
833 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
836 DEBUGpic16_emitcode("%s:%d immediate", __FILE__, __LINE__);
838 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
841 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
843 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
846 PCOI(aop->aopu.pcop)->index = val;
848 DEBUGpic16_emitcode("%s:%d dir", __FILE__, __LINE__);
850 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
851 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
852 // aop->size = AOP_SIZE( IC_LEFT(ic) );
856 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
857 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
859 val, IS_PTR_CONST(operandType(op)));
861 val, IS_CODEPTR(operandType(op)));
864 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
866 pic16_allocDirReg (IC_LEFT(ic));
868 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
874 static int aopIdx (asmop *aop, int offset)
879 if(aop->type != AOP_REG)
882 return aop->aopu.aop_reg[offset]->rIdx;
885 /*-----------------------------------------------------------------*/
886 /* regsInCommon - two operands have some registers in common */
887 /*-----------------------------------------------------------------*/
888 static bool regsInCommon (operand *op1, operand *op2)
893 /* if they have registers in common */
894 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
897 sym1 = OP_SYMBOL(op1);
898 sym2 = OP_SYMBOL(op2);
900 if (sym1->nRegs == 0 || sym2->nRegs == 0)
903 for (i = 0 ; i < sym1->nRegs ; i++) {
908 for (j = 0 ; j < sym2->nRegs ;j++ ) {
912 if (sym2->regs[j] == sym1->regs[i])
920 /*-----------------------------------------------------------------*/
921 /* operandsEqu - equivalent */
922 /*-----------------------------------------------------------------*/
923 static bool operandsEqu ( operand *op1, operand *op2)
927 /* if they not symbols */
928 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
931 sym1 = OP_SYMBOL(op1);
932 sym2 = OP_SYMBOL(op2);
934 /* if both are itemps & one is spilt
935 and the other is not then false */
936 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
937 sym1->isspilt != sym2->isspilt )
940 /* if they are the same */
944 if (sym1->rname[0] && sym2->rname[0]
945 && strcmp (sym1->rname, sym2->rname) == 0)
949 /* if left is a tmp & right is not */
953 (sym1->usl.spillLoc == sym2))
960 (sym2->usl.spillLoc == sym1))
966 /*-----------------------------------------------------------------*/
967 /* pic16_sameRegs - two asmops have the same registers */
968 /*-----------------------------------------------------------------*/
969 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
976 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
977 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
979 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
981 if (aop1->type != AOP_REG ||
982 aop2->type != AOP_REG )
985 if (aop1->size != aop2->size )
988 for (i = 0 ; i < aop1->size ; i++ )
989 if (aop1->aopu.aop_reg[i] !=
990 aop2->aopu.aop_reg[i] )
996 /*-----------------------------------------------------------------*/
997 /* pic16_aopOp - allocates an asmop for an operand : */
998 /*-----------------------------------------------------------------*/
999 void pic16_aopOp (operand *op, iCode *ic, bool result)
1008 // DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1010 /* if this a literal */
1011 if (IS_OP_LITERAL(op)) {
1012 op->aop = aop = newAsmop(AOP_LIT);
1013 aop->aopu.aop_lit = op->operand.valOperand;
1014 aop->size = getSize(operandType(op));
1019 sym_link *type = operandType(op);
1021 if(IS_PTR_CONST(type))
1023 if(IS_CODEPTR(type))
1025 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1028 /* if already has a asmop then continue */
1032 /* if the underlying symbol has a aop */
1033 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1034 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1035 op->aop = OP_SYMBOL(op)->aop;
1039 /* if this is a true symbol */
1040 if (IS_TRUE_SYMOP(op)) {
1041 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1042 op->aop = aopForSym(ic, op, result);
1046 /* this is a temporary : this has
1052 e) can be a return use only */
1054 sym = OP_SYMBOL(op);
1056 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
1057 /* if the type is a conditional */
1058 if (sym->regType == REG_CND) {
1059 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1064 /* if it is spilt then two situations
1066 b) has a spill location */
1067 if (sym->isspilt || sym->nRegs == 0) {
1069 DEBUGpic16_emitcode(";","%d",__LINE__);
1070 /* rematerialize it NOW */
1073 sym->aop = op->aop = aop =
1075 aop->size = getSize(sym->type);
1076 //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1083 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1084 aop->size = getSize(sym->type);
1085 for ( i = 0 ; i < 1 ; i++ ) {
1086 aop->aopu.aop_str[i] = accUse[i];
1087 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1089 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1090 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1098 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1099 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1100 //pic16_allocDirReg (IC_LEFT(ic));
1101 aop->size = getSize(sym->type);
1106 aop = op->aop = sym->aop = newAsmop(AOP_STR);
1107 aop->size = getSize(sym->type);
1108 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1109 aop->aopu.aop_str[i] = fReturn[i];
1111 DEBUGpic16_emitcode(";","%d",__LINE__);
1115 /* else spill location */
1116 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1117 /* force a new aop if sizes differ */
1118 sym->usl.spillLoc->aop = NULL;
1120 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1121 __FUNCTION__,__LINE__,
1122 sym->usl.spillLoc->rname,
1123 sym->rname, sym->usl.spillLoc->offset);
1125 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1126 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1127 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1129 sym->usl.spillLoc->offset, op);
1130 aop->size = getSize(sym->type);
1136 sym_link *type = operandType(op);
1138 if(IS_PTR_CONST(type))
1140 if(IS_CODEPTR(type))
1142 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1145 /* must be in a register */
1146 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1147 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1148 aop->size = sym->nRegs;
1149 for ( i = 0 ; i < sym->nRegs ;i++)
1150 aop->aopu.aop_reg[i] = sym->regs[i];
1153 /*-----------------------------------------------------------------*/
1154 /* pic16_freeAsmop - free up the asmop given to an operand */
1155 /*----------------------------------------------------------------*/
1156 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1173 /* depending on the asmop type only three cases need work AOP_RO
1174 , AOP_R1 && AOP_STK */
1176 switch (aop->type) {
1178 if (_G.fsr0Pushed ) {
1180 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1181 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1182 // pic16_emitcode ("pop","ar0");
1186 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1190 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1196 pic16_emitcode ("pop","ar0");
1200 bitVectUnSetBit(ic->rUsed,R0_IDX);
1206 pic16_emitcode ("pop","ar1");
1210 bitVectUnSetBit(ic->rUsed,R1_IDX);
1216 int stk = aop->aopu.aop_stk + aop->size;
1217 bitVectUnSetBit(ic->rUsed,R0_IDX);
1218 bitVectUnSetBit(ic->rUsed,R1_IDX);
1220 getFreePtr(ic,&aop,FALSE);
1222 if (options.stack10bit)
1224 /* I'm not sure what to do here yet... */
1227 "*** Warning: probably generating bad code for "
1228 "10 bit stack mode.\n");
1232 pic16_emitcode ("mov","a,_bp");
1233 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1234 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1236 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1240 pic16_emitcode("pop","acc");
1241 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1243 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1246 pic16_freeAsmop(op,NULL,ic,TRUE);
1248 pic16_emitcode("pop","ar0");
1253 pic16_emitcode("pop","ar1");
1261 /* all other cases just dealloc */
1265 OP_SYMBOL(op)->aop = NULL;
1266 /* if the symbol has a spill */
1268 SPIL_LOC(op)->aop = NULL;
1273 /*-----------------------------------------------------------------*/
1274 /* pic16_aopGet - for fetching value of the aop */
1275 /*-----------------------------------------------------------------*/
1276 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1281 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1283 /* offset is greater than size then zero */
1284 if (offset > (aop->size - 1) &&
1285 aop->type != AOP_LIT)
1288 /* depending on type */
1289 switch (aop->type) {
1293 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1294 rs = Safe_calloc(1, strlen(s)+1);
1299 /* if we need to increment it */
1300 while (offset > aop->coff)
1302 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1306 while (offset < aop->coff)
1308 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1314 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1315 return (dname ? "acc" : "a");
1317 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1318 rs = Safe_calloc (1, strlen (s) + 1);
1326 sprintf (s,"%s",aop->aopu.aop_immd);
1329 sprintf(s,"(%s >> %d)",
1334 aop->aopu.aop_immd);
1335 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1336 rs = Safe_calloc(1,strlen(s)+1);
1342 sprintf(s,"(%s + %d)",
1345 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1347 sprintf(s,"%s",aop->aopu.aop_dir);
1348 rs = Safe_calloc(1,strlen(s)+1);
1354 // return aop->aopu.aop_reg[offset]->dname;
1356 return aop->aopu.aop_reg[offset]->name;
1359 //pic16_emitcode(";","%d",__LINE__);
1360 return aop->aopu.aop_dir;
1363 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1364 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1366 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1367 rs = Safe_strdup("WREG");
1371 sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1372 rs = Safe_calloc(1,strlen(s)+1);
1377 aop->coff = offset ;
1378 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1381 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1383 return aop->aopu.aop_str[offset];
1387 pCodeOp *pcop = aop->aopu.pcop;
1388 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1390 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1391 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1392 sprintf(s,"%s", pcop->name);
1394 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1397 rs = Safe_calloc(1,strlen(s)+1);
1402 // pCodeOp *pcop = aop->aop
1407 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1408 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1409 "aopget got unsupported aop->type");
1414 /*-----------------------------------------------------------------*/
1415 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1416 /*-----------------------------------------------------------------*/
1417 pCodeOp *pic16_popGetTempReg(void)
1422 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1427 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1428 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1429 PCOR(pcop)->r->wasUsed=1;
1430 PCOR(pcop)->r->isFree=0;
1432 /* push value on stack */
1433 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1441 /*-----------------------------------------------------------------*/
1442 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1443 /*-----------------------------------------------------------------*/
1444 void pic16_popReleaseTempReg(pCodeOp *pcop)
1446 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1448 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1449 PCOR(pcop)->r->isFree = 1;
1451 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1454 /*-----------------------------------------------------------------*/
1455 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1456 /*-----------------------------------------------------------------*/
1457 pCodeOp *pic16_popGetLabel(unsigned int key)
1460 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1465 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1468 /*-----------------------------------------------------------------*/
1469 /* pic16_popCopyReg - copy a pcode operator */
1470 /*-----------------------------------------------------------------*/
1471 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1475 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1476 pcor->pcop.type = pc->pcop.type;
1478 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1479 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1481 pcor->pcop.name = NULL;
1484 pcor->rIdx = pc->rIdx;
1487 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1492 /*-----------------------------------------------------------------*/
1493 /* pic16_popGetLit - asm operator to pcode operator conversion */
1494 /*-----------------------------------------------------------------*/
1495 pCodeOp *pic16_popGetLit(unsigned int lit)
1497 return pic16_newpCodeOpLit(lit);
1500 /*-----------------------------------------------------------------*/
1501 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1502 /*-----------------------------------------------------------------*/
1503 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1505 return pic16_newpCodeOpLit2(lit, arg2);
1509 /*-----------------------------------------------------------------*/
1510 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1511 /*-----------------------------------------------------------------*/
1512 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1514 return pic16_newpCodeOpImmd(name, offset,index, 0);
1518 /*-----------------------------------------------------------------*/
1519 /* pic16_popGet - asm operator to pcode operator conversion */
1520 /*-----------------------------------------------------------------*/
1521 pCodeOp *pic16_popGetWithString(char *str)
1527 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1531 pcop = pic16_newpCodeOp(str,PO_STR);
1536 /*-----------------------------------------------------------------*/
1537 /* pic16_popRegFromString - */
1538 /*-----------------------------------------------------------------*/
1539 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1542 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1543 pcop->type = PO_DIR;
1545 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1546 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1551 pcop->name = Safe_calloc(1,strlen(str)+1);
1552 strcpy(pcop->name,str);
1554 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1556 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1557 if(PCOR(pcop)->r == NULL) {
1558 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1559 // __FUNCTION__, __LINE__, str, size, offset);
1562 // PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1563 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1565 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1567 // DEBUGpic16_emitcode(";","%d %s size= %d offset=%d",__LINE__,pcop->name,size,offset);
1569 PCOR(pcop)->instance = offset;
1574 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1578 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1580 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1581 PCOR(pcop)->rIdx = rIdx;
1582 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1584 PCOR(pcop)->r->isFree = 0;
1585 PCOR(pcop)->r->wasUsed = 1;
1587 pcop->type = PCOR(pcop)->r->pc_type;
1592 /*---------------------------------------------------------------------------------*/
1593 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1595 /*---------------------------------------------------------------------------------*/
1596 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1601 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1603 /* comment the following check, so errors to throw up */
1604 // if(!pcop2)return NULL;
1606 temp = pic16_popGet(aop_dst, offset);
1607 pcop2->pcop2 = temp;
1614 /*--------------------------------------------------------------------------------.-*/
1615 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1616 /* VR 030601 , adapted by Hans Dorn */
1617 /*--------------------------------------------------------------------------------.-*/
1618 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1622 pcop2 = (pCodeOpReg2 *)src;
1630 /*---------------------------------------------------------------------------------*/
1631 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1632 /* movff instruction */
1633 /*---------------------------------------------------------------------------------*/
1634 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1639 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1640 pcop2->pcop2 = pic16_popCopyReg(dst);
1642 /* the pCodeOp may be already allocated */
1643 pcop2 = (pCodeOpReg2 *)(src);
1644 pcop2->pcop2 = (pCodeOp *)(dst);
1651 /*-----------------------------------------------------------------*/
1652 /* pic16_popGet - asm operator to pcode operator conversion */
1653 /*-----------------------------------------------------------------*/
1654 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1656 //char *s = buffer ;
1660 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1661 /* offset is greater than
1664 // if (offset > (aop->size - 1) &&
1665 // aop->type != AOP_LIT)
1666 // return NULL; //zero;
1668 /* depending on type */
1669 switch (aop->type) {
1675 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1676 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1683 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1684 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
1685 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1686 PCOR(pcop)->r->wasUsed = 1;
1687 PCOR(pcop)->r->isFree = 0;
1689 PCOR(pcop)->instance = offset;
1690 pcop->type = PCOR(pcop)->r->pc_type;
1694 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1695 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1699 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
1701 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1703 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1705 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1706 PCOR(pcop)->rIdx = rIdx;
1707 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1708 PCOR(pcop)->r->wasUsed=1;
1709 PCOR(pcop)->r->isFree=0;
1711 PCOR(pcop)->instance = offset;
1712 pcop->type = PCOR(pcop)->r->pc_type;
1713 // rs = aop->aopu.aop_reg[offset]->name;
1714 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1718 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1719 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1725 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1726 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1730 int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1732 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1734 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1735 // pcop->type = PO_GPR_REGISTER;
1736 PCOR(pcop)->rIdx = rIdx;
1737 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
1738 PCOR(pcop)->r->wasUsed=1;
1739 PCOR(pcop)->r->isFree=0;
1741 PCOR(pcop)->instance = offset;
1742 pcop->type = PCOR(pcop)->r->pc_type;
1743 rs = aop->aopu.aop_reg[offset]->name;
1744 DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1749 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1751 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1752 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1753 //if(PCOR(pcop)->r == NULL)
1754 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1758 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1759 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1762 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1763 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1766 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1767 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1768 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1769 pcop->type = PCOR(pcop)->r->pc_type;
1770 pcop->name = PCOR(pcop)->r->name;
1776 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1778 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1779 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1781 switch( aop->aopu.pcop->type ) {
1782 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1783 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1785 assert( 0 ); /* should never reach here */;
1788 PCOI(pcop)->offset = offset;
1793 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1794 "pic16_popGet got unsupported aop->type");
1797 /*-----------------------------------------------------------------*/
1798 /* pic16_aopPut - puts a string for a aop */
1799 /*-----------------------------------------------------------------*/
1800 void pic16_aopPut (asmop *aop, char *s, int offset)
1805 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1807 if (aop->size && offset > ( aop->size - 1)) {
1808 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1809 "pic16_aopPut got offset > aop->size");
1813 /* will assign value to value */
1814 /* depending on where it is ofcourse */
1815 switch (aop->type) {
1818 sprintf(d,"(%s + %d)",
1819 aop->aopu.aop_dir,offset);
1820 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1823 sprintf(d,"%s",aop->aopu.aop_dir);
1826 DEBUGpic16_emitcode(";","%d",__LINE__);
1828 pic16_emitcode("movf","%s,w",s);
1829 pic16_emitcode("movwf","%s",d);
1832 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
1833 if(offset >= aop->size) {
1834 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1837 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1840 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1847 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1848 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1851 strcmp(s,"r0") == 0 ||
1852 strcmp(s,"r1") == 0 ||
1853 strcmp(s,"r2") == 0 ||
1854 strcmp(s,"r3") == 0 ||
1855 strcmp(s,"r4") == 0 ||
1856 strcmp(s,"r5") == 0 ||
1857 strcmp(s,"r6") == 0 ||
1858 strcmp(s,"r7") == 0 )
1859 pic16_emitcode("mov","%s,%s ; %d",
1860 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1864 if(strcmp(s,"W")==0 )
1865 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
1867 pic16_emitcode("movwf","%s",
1868 aop->aopu.aop_reg[offset]->name);
1870 if(strcmp(s,zero)==0) {
1871 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1873 } else if(strcmp(s,"W")==0) {
1874 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1875 pcop->type = PO_GPR_REGISTER;
1877 PCOR(pcop)->rIdx = -1;
1878 PCOR(pcop)->r = NULL;
1880 DEBUGpic16_emitcode(";","%d",__LINE__);
1881 pcop->name = Safe_strdup(s);
1882 pic16_emitpcode(POC_MOVFW,pcop);
1883 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1884 } else if(strcmp(s,one)==0) {
1885 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1886 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1888 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1896 if (aop->type == AOP_DPTR2)
1902 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1903 "pic16_aopPut writting to code space");
1907 while (offset > aop->coff) {
1909 pic16_emitcode ("inc","dptr");
1912 while (offset < aop->coff) {
1914 pic16_emitcode("lcall","__decdptr");
1919 /* if not in accumulater */
1922 pic16_emitcode ("movx","@dptr,a");
1924 if (aop->type == AOP_DPTR2)
1932 while (offset > aop->coff) {
1934 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1936 while (offset < aop->coff) {
1938 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1944 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1949 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1951 if (strcmp(s,"r0") == 0 ||
1952 strcmp(s,"r1") == 0 ||
1953 strcmp(s,"r2") == 0 ||
1954 strcmp(s,"r3") == 0 ||
1955 strcmp(s,"r4") == 0 ||
1956 strcmp(s,"r5") == 0 ||
1957 strcmp(s,"r6") == 0 ||
1958 strcmp(s,"r7") == 0 ) {
1960 sprintf(buffer,"a%s",s);
1961 pic16_emitcode("mov","@%s,%s",
1962 aop->aopu.aop_ptr->name,buffer);
1964 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1969 if (strcmp(s,"a") == 0)
1970 pic16_emitcode("push","acc");
1972 pic16_emitcode("push","%s",s);
1977 /* if bit variable */
1978 if (!aop->aopu.aop_dir) {
1979 pic16_emitcode("clr","a");
1980 pic16_emitcode("rlc","a");
1983 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1986 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1989 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1991 lbl = newiTempLabel(NULL);
1993 if (strcmp(s,"a")) {
1996 pic16_emitcode("clr","c");
1997 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1998 pic16_emitcode("cpl","c");
1999 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2000 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2007 if (strcmp(aop->aopu.aop_str[offset],s))
2008 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2013 if (!offset && (strcmp(s,"acc") == 0))
2016 if (strcmp(aop->aopu.aop_str[offset],s))
2017 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2021 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2022 "pic16_aopPut got unsupported aop->type");
2028 /*-----------------------------------------------------------------*/
2029 /* mov2w - generate either a MOVLW or MOVFW based operand type */
2030 /*-----------------------------------------------------------------*/
2031 static void mov2w (asmop *aop, int offset)
2037 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2040 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2042 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2047 /* push pcop into stack */
2048 void pic16_pushpCodeOp(pCodeOp *pcop)
2050 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2051 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2054 /* pop pcop from stack */
2055 void pic16_poppCodeOp(pCodeOp *pcop)
2057 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2061 /*-----------------------------------------------------------------*/
2062 /* pushw - pushes wreg to stack */
2063 /*-----------------------------------------------------------------*/
2066 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2067 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2071 /*-----------------------------------------------------------------*/
2072 /* pushaop - pushes aop to stack */
2073 /*-----------------------------------------------------------------*/
2074 void pushaop(asmop *aop, int offset)
2076 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2077 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2080 /*-----------------------------------------------------------------*/
2081 /* popaop - pops aop from stack */
2082 /*-----------------------------------------------------------------*/
2083 void popaop(asmop *aop, int offset)
2085 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2086 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2089 void popaopidx(asmop *aop, int offset, int index)
2093 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2095 if(STACK_MODEL_LARGE)ofs++;
2097 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2098 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2101 /*-----------------------------------------------------------------*/
2102 /* reAdjustPreg - points a register back to where it should */
2103 /*-----------------------------------------------------------------*/
2104 static void reAdjustPreg (asmop *aop)
2108 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2110 if ((size = aop->size) <= 1)
2113 switch (aop->type) {
2117 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2121 if (aop->type == AOP_DPTR2)
2127 pic16_emitcode("lcall","__decdptr");
2130 if (aop->type == AOP_DPTR2)
2142 /*-----------------------------------------------------------------*/
2143 /* opIsGptr: returns non-zero if the passed operand is */
2144 /* a generic pointer type. */
2145 /*-----------------------------------------------------------------*/
2146 static int opIsGptr(operand *op)
2148 sym_link *type = operandType(op);
2150 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2151 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2159 /*-----------------------------------------------------------------*/
2160 /* pic16_getDataSize - get the operand data size */
2161 /*-----------------------------------------------------------------*/
2162 int pic16_getDataSize(operand *op)
2164 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2167 return AOP_SIZE(op);
2169 // tsd- in the pic port, the genptr size is 1, so this code here
2170 // fails. ( in the 8051 port, the size was 4).
2173 size = AOP_SIZE(op);
2174 if (size == GPTRSIZE)
2176 sym_link *type = operandType(op);
2177 if (IS_GENPTR(type))
2179 /* generic pointer; arithmetic operations
2180 * should ignore the high byte (pointer type).
2183 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2190 /*-----------------------------------------------------------------*/
2191 /* pic16_outAcc - output Acc */
2192 /*-----------------------------------------------------------------*/
2193 void pic16_outAcc(operand *result)
2196 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2197 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2200 size = pic16_getDataSize(result);
2202 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2205 /* unsigned or positive */
2207 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2212 /*-----------------------------------------------------------------*/
2213 /* pic16_outBitC - output a bit C */
2214 /* Move to result the value of Carry flag -- VR */
2215 /*-----------------------------------------------------------------*/
2216 void pic16_outBitC(operand *result)
2220 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2221 /* if the result is bit */
2222 if (AOP_TYPE(result) == AOP_CRY) {
2223 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2224 pic16_aopPut(AOP(result),"c",0);
2227 i = AOP_SIZE(result);
2229 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2231 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2234 pic16_emitcode("clr","a ; %d", __LINE__);
2235 pic16_emitcode("rlc","a");
2236 pic16_outAcc(result);
2241 /*-----------------------------------------------------------------*/
2242 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2243 /*-----------------------------------------------------------------*/
2244 void pic16_toBoolean(operand *oper)
2246 int size = AOP_SIZE(oper) - 1;
2249 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2251 if ( AOP_TYPE(oper) != AOP_ACC) {
2252 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2255 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2260 #if !defined(GEN_Not)
2261 /*-----------------------------------------------------------------*/
2262 /* genNot - generate code for ! operation */
2263 /*-----------------------------------------------------------------*/
2264 static void pic16_genNot (iCode *ic)
2269 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2270 /* assign asmOps to operand & result */
2271 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2272 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2274 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2275 /* if in bit space then a special case */
2276 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2277 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2278 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2279 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2281 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2282 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2283 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2288 size = AOP_SIZE(IC_LEFT(ic));
2290 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2291 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2292 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2295 pic16_toBoolean(IC_LEFT(ic));
2297 tlbl = newiTempLabel(NULL);
2298 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2299 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2300 pic16_outBitC(IC_RESULT(ic));
2303 /* release the aops */
2304 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2305 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2310 #if !defined(GEN_Cpl)
2311 /*-----------------------------------------------------------------*/
2312 /* genCpl - generate code for complement */
2313 /*-----------------------------------------------------------------*/
2314 static void pic16_genCpl (iCode *ic)
2320 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2321 /* assign asmOps to operand & result */
2322 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2323 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2325 /* if both are in bit space then
2327 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2328 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2330 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2331 pic16_emitcode("cpl","c");
2332 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2336 size = AOP_SIZE(IC_RESULT(ic));
2339 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2341 pic16_emitcode("cpl","a");
2342 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2344 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2345 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2347 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2348 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2356 /* release the aops */
2357 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2358 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2362 /*-----------------------------------------------------------------*/
2363 /* genUminusFloat - unary minus for floating points */
2364 /*-----------------------------------------------------------------*/
2365 static void genUminusFloat(operand *op,operand *result)
2367 int size ,offset =0 ;
2370 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2371 /* for this we just need to flip the
2372 first it then copy the rest in place */
2373 size = AOP_SIZE(op) - 1;
2374 l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2378 pic16_emitcode("cpl","acc.7");
2379 pic16_aopPut(AOP(result),"a",3);
2382 pic16_aopPut(AOP(result),
2383 pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2389 /*-----------------------------------------------------------------*/
2390 /* genUminus - unary minus code generation */
2391 /*-----------------------------------------------------------------*/
2392 static void genUminus (iCode *ic)
2395 sym_link *optype, *rtype;
2397 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2400 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2401 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2403 /* if both in bit space then special case */
2404 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2405 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2407 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2408 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2409 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2414 optype = operandType(IC_LEFT(ic));
2415 rtype = operandType(IC_RESULT(ic));
2417 /* if float then do float stuff */
2418 if (IS_FLOAT(optype)) {
2419 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2423 /* otherwise subtract from zero by taking the 2's complement */
2424 size = AOP_SIZE(IC_LEFT(ic));
2426 for(i=0; i<size; i++) {
2427 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2428 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)),i));
2430 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2431 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2435 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2436 for(i=1; i<size; i++) {
2438 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2442 /* release the aops */
2443 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2444 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2447 /*-----------------------------------------------------------------*/
2448 /* saveRegisters - will look for a call and save the registers */
2449 /*-----------------------------------------------------------------*/
2450 static void saveRegisters(iCode *lic)
2457 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2459 for (ic = lic ; ic ; ic = ic->next)
2460 if (ic->op == CALL || ic->op == PCALL)
2464 fprintf(stderr,"found parameter push with no function call\n");
2468 /* if the registers have been saved already then
2470 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2473 /* find the registers in use at this time
2474 and push them away to safety */
2475 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2479 if (options.useXstack) {
2480 if (bitVectBitValue(rsave,R0_IDX))
2481 pic16_emitcode("mov","b,r0");
2482 pic16_emitcode("mov","r0,%s",spname);
2483 for (i = 0 ; i < pic16_nRegs ; i++) {
2484 if (bitVectBitValue(rsave,i)) {
2486 pic16_emitcode("mov","a,b");
2488 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2489 pic16_emitcode("movx","@r0,a");
2490 pic16_emitcode("inc","r0");
2493 pic16_emitcode("mov","%s,r0",spname);
2494 if (bitVectBitValue(rsave,R0_IDX))
2495 pic16_emitcode("mov","r0,b");
2497 //for (i = 0 ; i < pic16_nRegs ; i++) {
2498 // if (bitVectBitValue(rsave,i))
2499 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2502 dtype = operandType(IC_LEFT(ic));
2503 if (currFunc && dtype &&
2504 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2505 IFFUNC_ISISR(currFunc->type) &&
2508 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2511 /*-----------------------------------------------------------------*/
2512 /* unsaveRegisters - pop the pushed registers */
2513 /*-----------------------------------------------------------------*/
2514 static void unsaveRegisters (iCode *ic)
2519 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2520 /* find the registers in use at this time
2521 and push them away to safety */
2522 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2525 if (options.useXstack) {
2526 pic16_emitcode("mov","r0,%s",spname);
2527 for (i = pic16_nRegs ; i >= 0 ; i--) {
2528 if (bitVectBitValue(rsave,i)) {
2529 pic16_emitcode("dec","r0");
2530 pic16_emitcode("movx","a,@r0");
2532 pic16_emitcode("mov","b,a");
2534 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2538 pic16_emitcode("mov","%s,r0",spname);
2539 if (bitVectBitValue(rsave,R0_IDX))
2540 pic16_emitcode("mov","r0,b");
2542 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2543 // if (bitVectBitValue(rsave,i))
2544 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2550 /*-----------------------------------------------------------------*/
2552 /*-----------------------------------------------------------------*/
2553 static void pushSide(operand * oper, int size)
2556 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2558 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2559 if (AOP_TYPE(oper) != AOP_REG &&
2560 AOP_TYPE(oper) != AOP_DIR &&
2562 pic16_emitcode("mov","a,%s",l);
2563 pic16_emitcode("push","acc");
2565 pic16_emitcode("push","%s",l);
2570 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2572 // (AOP(left)->aopu.pcop->type == PO_DIR)?
2574 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2575 pic16_emitpcode(POC_MOVFW, src);
2576 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2578 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2579 src, pic16_popGet(AOP(op), offset)));
2584 /*-----------------------------------------------------------------*/
2585 /* assignResultValue - assign results to oper, rescall==1 is */
2586 /* called from genCall() or genPCall() */
2587 /*-----------------------------------------------------------------*/
2588 static void assignResultValue(operand * oper, int rescall)
2590 int size = AOP_SIZE(oper);
2592 DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2593 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2596 /* assign result from a call/pcall function() */
2598 /* function results are stored in a special order,
2599 * see top of file with Function return policy, or manual */
2602 /* 8-bits, result in WREG */
2603 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2606 /* 16-bits, result in PRODL:WREG */
2607 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2611 /* 24-bits, result in PRODH:PRODL:WREG */
2612 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2616 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2617 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2620 /* >32-bits, result on stack, and FSR0 points to beginning.
2621 * Fix stack when done */
2624 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2625 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2627 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2632 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2633 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2634 if(STACK_MODEL_LARGE) {
2636 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2640 if(!GpsuedoStkPtr) {
2641 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2642 /* The last byte in the assignment is in W */
2644 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2649 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2650 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2652 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2658 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2660 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2670 /*-----------------------------------------------------------------*/
2671 /* genIpush - genrate code for pushing this gets a little complex */
2672 /*-----------------------------------------------------------------*/
2673 static void genIpush (iCode *ic)
2677 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2680 pic16_aopOp(IC_LEFT(ic), ic, FALSE);
2683 size = AOP_SIZE( IC_LEFT(ic) );
2686 mov2w( AOP(IC_LEFT(ic)), offset );
2692 int size, offset = 0 ;
2696 /* if this is not a parm push : ie. it is spill push
2697 and spill push is always done on the local stack */
2698 if (!ic->parmPush) {
2700 /* and the item is spilt then do nothing */
2701 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2704 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2705 size = AOP_SIZE(IC_LEFT(ic));
2706 /* push it on the stack */
2708 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2713 pic16_emitcode("push","%s",l);
2718 /* this is a paramter push: in this case we call
2719 the routine to find the call and save those
2720 registers that need to be saved */
2723 /* then do the push */
2724 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2727 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2728 size = AOP_SIZE(IC_LEFT(ic));
2731 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2732 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
2733 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2735 pic16_emitcode("mov","a,%s",l);
2736 pic16_emitcode("push","acc");
2738 pic16_emitcode("push","%s",l);
2741 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2745 /*-----------------------------------------------------------------*/
2746 /* genIpop - recover the registers: can happen only for spilling */
2747 /*-----------------------------------------------------------------*/
2748 static void genIpop (iCode *ic)
2750 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2755 /* if the temp was not pushed then */
2756 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2759 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2760 size = AOP_SIZE(IC_LEFT(ic));
2763 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2766 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2770 /*-----------------------------------------------------------------*/
2771 /* unsaverbank - restores the resgister bank from stack */
2772 /*-----------------------------------------------------------------*/
2773 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2775 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2781 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2783 if (options.useXstack) {
2785 r = getFreePtr(ic,&aop,FALSE);
2788 pic16_emitcode("mov","%s,_spx",r->name);
2789 pic16_emitcode("movx","a,@%s",r->name);
2790 pic16_emitcode("mov","psw,a");
2791 pic16_emitcode("dec","%s",r->name);
2794 pic16_emitcode ("pop","psw");
2797 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2798 if (options.useXstack) {
2799 pic16_emitcode("movx","a,@%s",r->name);
2800 //pic16_emitcode("mov","(%s+%d),a",
2801 // regspic16[i].base,8*bank+regspic16[i].offset);
2802 pic16_emitcode("dec","%s",r->name);
2805 pic16_emitcode("pop",""); //"(%s+%d)",
2806 //regspic16[i].base,8*bank); //+regspic16[i].offset);
2809 if (options.useXstack) {
2811 pic16_emitcode("mov","_spx,%s",r->name);
2812 pic16_freeAsmop(NULL,aop,ic,TRUE);
2818 /*-----------------------------------------------------------------*/
2819 /* saverbank - saves an entire register bank on the stack */
2820 /*-----------------------------------------------------------------*/
2821 static void saverbank (int bank, iCode *ic, bool pushPsw)
2823 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
2829 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2830 if (options.useXstack) {
2833 r = getFreePtr(ic,&aop,FALSE);
2834 pic16_emitcode("mov","%s,_spx",r->name);
2838 for (i = 0 ; i < pic16_nRegs ;i++) {
2839 if (options.useXstack) {
2840 pic16_emitcode("inc","%s",r->name);
2841 //pic16_emitcode("mov","a,(%s+%d)",
2842 // regspic16[i].base,8*bank+regspic16[i].offset);
2843 pic16_emitcode("movx","@%s,a",r->name);
2845 pic16_emitcode("push","");// "(%s+%d)",
2846 //regspic16[i].base,8*bank+regspic16[i].offset);
2850 if (options.useXstack) {
2851 pic16_emitcode("mov","a,psw");
2852 pic16_emitcode("movx","@%s,a",r->name);
2853 pic16_emitcode("inc","%s",r->name);
2854 pic16_emitcode("mov","_spx,%s",r->name);
2855 pic16_freeAsmop (NULL,aop,ic,TRUE);
2858 pic16_emitcode("push","psw");
2860 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2868 /*-----------------------------------------------------------------*/
2869 /* genCall - generates a call statement */
2870 /*-----------------------------------------------------------------*/
2871 static void genCall (iCode *ic)
2876 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2878 /* if caller saves & we have not saved then */
2882 /* if we are calling a function that is not using
2883 * the same register bank then we need to save the
2884 * destination registers on the stack */
2885 dtype = operandType(IC_LEFT(ic));
2886 if (currFunc && dtype &&
2887 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2888 IFFUNC_ISISR(currFunc->type) &&
2891 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2894 /* initialise stackParms for IPUSH pushes */
2895 // stackParms = psuedoStkPtr;
2896 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2898 /* if send set is not empty the assign */
2902 /* For the Pic port, there is no data stack.
2903 * So parameters passed to functions are stored
2904 * in registers. (The pCode optimizer will get
2905 * rid of most of these :). */
2907 int psuedoStkPtr=-1;
2908 int firstTimeThruLoop = 1;
2910 _G.sendSet = reverseSet(_G.sendSet);
2912 /* First figure how many parameters are getting passed */
2913 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2914 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2915 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2916 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2919 stackParms = psuedoStkPtr;
2921 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2922 int size, offset = 0;
2924 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2925 size = AOP_SIZE(IC_LEFT(sic));
2928 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2929 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2930 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2932 if(!firstTimeThruLoop) {
2933 /* If this is not the first time we've been through the loop
2934 * then we need to save the parameter in a temporary
2935 * register. The last byte of the last parameter is
2939 --psuedoStkPtr; // sanity check
2942 firstTimeThruLoop=0;
2944 mov2w (AOP(IC_LEFT(sic)), offset);
2947 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2953 pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2954 OP_SYMBOL(IC_LEFT(ic))->rname :
2955 OP_SYMBOL(IC_LEFT(ic))->name));
2958 /* if we need assign a result value */
2959 if ((IS_ITEMP(IC_RESULT(ic)) &&
2960 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2961 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2962 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2965 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2968 assignResultValue(IC_RESULT(ic), 1);
2970 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2971 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2973 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2976 if(!stackParms && ic->parmBytes) {
2977 stackParms = ic->parmBytes;
2981 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2982 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2983 if(STACK_MODEL_LARGE) {
2985 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2989 /* adjust the stack for parameters if required */
2990 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2992 if (ic->parmBytes) {
2995 if (ic->parmBytes > 3) {
2996 pic16_emitcode("mov","a,%s",spname);
2997 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2998 pic16_emitcode("mov","%s,a",spname);
3000 for ( i = 0 ; i < ic->parmBytes ;i++)
3001 pic16_emitcode("dec","%s",spname);
3006 /* if register bank was saved then pop them */
3008 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3010 /* if we hade saved some registers then unsave them */
3011 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3012 unsaveRegisters (ic);
3018 /*-----------------------------------------------------------------*/ // patch 14
3019 /* genPcall - generates a call by pointer statement */
3020 /*-----------------------------------------------------------------*/
3022 // new version, created from genCall
3024 static void genPcall (iCode *ic)
3028 symbol *retlbl = newiTempLabel(NULL);
3029 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3031 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3033 /* if caller saves & we have not saved then */
3037 /* if we are calling a function that is not using
3038 * the same register bank then we need to save the
3039 * destination registers on the stack */
3040 dtype = operandType(IC_LEFT(ic));
3041 if (currFunc && dtype &&
3042 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
3043 IFFUNC_ISISR(currFunc->type) &&
3046 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3048 /* if send set is not empty the assign */
3052 /* For the Pic port, there is no data stack.
3053 * So parameters passed to functions are stored
3054 * in registers. (The pCode optimizer will get
3055 * rid of most of these :). */
3057 int psuedoStkPtr=-1;
3058 int firstTimeThruLoop = 1;
3060 _G.sendSet = reverseSet(_G.sendSet);
3062 /* First figure how many parameters are getting passed */
3063 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3064 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3065 psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
3066 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
3069 stackParms = psuedoStkPtr;
3071 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3072 int size, offset = 0;
3074 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3075 size = AOP_SIZE(IC_LEFT(sic));
3078 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3079 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3080 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3082 if(!firstTimeThruLoop) {
3083 /* If this is not the first time we've been through the loop
3084 * then we need to save the parameter in a temporary
3085 * register. The last byte of the last parameter is
3089 --psuedoStkPtr; // sanity check
3092 firstTimeThruLoop=0;
3094 mov2w (AOP(IC_LEFT(sic)), offset);
3097 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3102 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3104 // push return address
3105 // push $ on return stack, then replace with retlbl
3107 pic16_emitpcodeNULLop(POC_PUSH);
3109 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3110 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3111 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3112 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3113 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3114 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3116 /* make the call by writing the pointer into pc */
3117 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3118 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3120 // note: MOVFF to PCL not allowed
3121 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3122 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3125 // pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key));
3126 // pic16_emitpcodeNULLop(POC_NOP);
3127 // pic16_emitpcodeNULLop(POC_NOP);
3129 /* return address is here: (X) */
3130 pic16_emitpLabelFORCE(retlbl->key);
3132 // pic16_emitpcodeNULLop(POC_NOP);
3134 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3137 /* if we need assign a result value */
3138 if ((IS_ITEMP(IC_RESULT(ic)) &&
3139 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3140 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
3141 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3144 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3147 assignResultValue(IC_RESULT(ic), 1);
3149 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3150 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3152 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3156 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3157 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3158 if(STACK_MODEL_LARGE) {
3160 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3164 /* adjust the stack for parameters if required */
3165 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3167 if (ic->parmBytes) {
3170 if (ic->parmBytes > 3) {
3171 pic16_emitcode("mov","a,%s",spname);
3172 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3173 pic16_emitcode("mov","%s,a",spname);
3175 for ( i = 0 ; i < ic->parmBytes ;i++)
3176 pic16_emitcode("dec","%s",spname);
3179 /* if register bank was saved then pop them */
3181 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3183 /* if we hade saved some registers then unsave them */
3184 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3185 unsaveRegisters (ic);
3190 // old version, kept for reference
3192 /*-----------------------------------------------------------------*/
3193 /* genPcall - generates a call by pointer statement */
3194 /*-----------------------------------------------------------------*/
3195 static void genPcall (iCode *ic)
3198 symbol *rlbl = newiTempLabel(NULL);
3201 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3202 /* if caller saves & we have not saved then */
3206 /* if we are calling a function that is not using
3207 the same register bank then we need to save the
3208 destination registers on the stack */
3209 dtype = operandType(IC_LEFT(ic));
3210 if (currFunc && dtype &&
3211 IFFUNC_ISISR(currFunc->type) &&
3212 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3213 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3216 /* push the return address on to the stack */
3217 pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3218 pic16_emitcode("push","acc");
3219 pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3220 pic16_emitcode("push","acc");
3222 if (options.model == MODEL_FLAT24)
3224 pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3225 pic16_emitcode("push","acc");
3228 /* now push the calling address */
3229 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3231 pushSide(IC_LEFT(ic), FPTRSIZE);
3233 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3235 /* if send set is not empty the assign */
3239 for (sic = setFirstItem(_G.sendSet) ; sic ;
3240 sic = setNextItem(_G.sendSet)) {
3241 int size, offset = 0;
3242 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3243 size = AOP_SIZE(IC_LEFT(sic));
3245 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3247 if (strcmp(l,fReturn[offset]))
3248 pic16_emitcode("mov","%s,%s",
3253 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3258 pic16_emitcode("ret","");
3259 pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3262 /* if we need assign a result value */
3263 if ((IS_ITEMP(IC_RESULT(ic)) &&
3264 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3265 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3266 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3269 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3272 assignResultValue(IC_RESULT(ic), 1);
3274 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3277 /* adjust the stack for parameters if
3279 if (ic->parmBytes) {
3281 if (ic->parmBytes > 3) {
3282 pic16_emitcode("mov","a,%s",spname);
3283 pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3284 pic16_emitcode("mov","%s,a",spname);
3286 for ( i = 0 ; i < ic->parmBytes ;i++)
3287 pic16_emitcode("dec","%s",spname);
3291 /* if register bank was saved then unsave them */
3292 if (currFunc && dtype &&
3293 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3294 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3296 /* if we hade saved some registers then
3299 unsaveRegisters (ic);
3305 /*-----------------------------------------------------------------*/
3306 /* resultRemat - result is rematerializable */
3307 /*-----------------------------------------------------------------*/
3308 static int resultRemat (iCode *ic)
3310 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3311 if (SKIP_IC(ic) || ic->op == IFX)
3314 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3315 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3316 if (sym->remat && !POINTER_SET(ic))
3323 #if defined(__BORLANDC__) || defined(_MSC_VER)
3324 #define STRCASECMP stricmp
3326 #define STRCASECMP strcasecmp
3330 /*-----------------------------------------------------------------*/
3331 /* inExcludeList - return 1 if the string is in exclude Reg list */
3332 /*-----------------------------------------------------------------*/
3333 static bool inExcludeList(char *s)
3335 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3338 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3339 if (options.excludeRegs[i] &&
3340 STRCASECMP(options.excludeRegs[i],"none") == 0)
3343 for ( i = 0 ; options.excludeRegs[i]; i++) {
3344 if (options.excludeRegs[i] &&
3345 STRCASECMP(s,options.excludeRegs[i]) == 0)
3352 /*-----------------------------------------------------------------*/
3353 /* genFunction - generated code for function entry */
3354 /*-----------------------------------------------------------------*/
3355 static void genFunction (iCode *ic)
3360 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3362 pic16_labelOffset += (max_key+4);
3367 ftype = operandType(IC_LEFT(ic));
3368 sym = OP_SYMBOL(IC_LEFT(ic));
3370 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3371 /* create an absolute section at the interrupt vector:
3372 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3380 sym = OP_SYMBOL( IC_LEFT(ic));
3382 if(interrupts[i]->name
3383 && !STRCASECMP(interrupts[i]->name, sym->name)) {
3390 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3391 __FILE__, __LINE__, sym->name);
3394 _G.interruptvector = found;
3397 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3398 asym = newSymbol(asymname, 0);
3400 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3401 pic16_addpBlock( apb );
3403 pic16_addpCode2pBlock(apb,
3404 pic16_newpCodeCharP(";-----------------------------------------"));
3407 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3409 pic16_addpCode2pBlock(apb,
3410 pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3412 /* mark the end of this tiny function */
3413 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3418 abSym = Safe_calloc(1, sizeof(absSym));
3419 abSym->name = Safe_strdup( asymname );
3421 switch( _G.interruptvector ) {
3422 case 0: abSym->address = 0x000000; break;
3423 case 1: abSym->address = 0x000008; break;
3424 case 2: abSym->address = 0x000018; break;
3427 /* relocate interrupt vectors if needed */
3428 abSym->address += pic16_options.ivt_loc;
3430 addSet(&absSymSet, abSym);
3435 /* create the function header */
3436 pic16_emitcode(";","-----------------------------------------");
3437 pic16_emitcode(";"," function %s",sym->name);
3438 pic16_emitcode(";","-----------------------------------------");
3440 pic16_emitcode("","%s:",sym->rname);
3441 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3447 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3448 if(!strcmp(ab->name, sym->name)) {
3449 pic16_pBlockConvert2Absolute(pb);
3456 if(IFFUNC_ISNAKED(ftype)) {
3457 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3461 /* if critical function then turn interrupts off */
3462 if (IFFUNC_ISCRITICAL(ftype))
3463 pic16_emitcode("clr","ea");
3465 /* if this is an interrupt service routine then
3466 * save acc, b, dpl, dph */
3467 if (IFFUNC_ISISR(sym->type)) {
3469 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3470 if(!(_G.interruptvector == 1)) {
3472 /* do not save WREG,STATUS,BSR for high priority interrupts
3473 * because they are stored in the hardware shadow registers already */
3475 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3476 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3477 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3480 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3481 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3482 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3483 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3485 // pic16_pBlockConvert2ISR(pb);
3487 /* if any registers used */
3488 if (sym->regsUsed) {
3489 /* save the registers used */
3490 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3491 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3492 if (bitVectBitValue(sym->regsUsed,i)) {
3494 fprintf(stderr, "%s:%d function %s uses register %s\n",
3495 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3496 pic16_regWithIdx(i)->name);
3499 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3502 if(!pic16_regWithIdx(i)->wasUsed) {
3503 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3504 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3506 pic16_regWithIdx(i)->wasUsed = 1;
3512 /* emit code to setup stack frame if user enabled,
3513 * and function is not main() */
3515 // fprintf(stderr, "function name: %s\n", sym->name);
3516 if(strcmp(sym->name, "main")) {
3517 if(/*!options.ommitFramePtr || */sym->regsUsed) {
3518 /* setup the stack frame */
3519 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3520 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3521 if(STACK_MODEL_LARGE)
3522 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3526 /* if callee-save to be used for this function
3527 * then save the registers being used in this function */
3528 // if (IFFUNC_CALLEESAVES(sym->type))
3532 // fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3534 // pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3536 /* if any registers used */
3537 if (sym->regsUsed) {
3538 /* save the registers used */
3539 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3540 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3541 if (bitVectBitValue(sym->regsUsed,i)) {
3544 fprintf(stderr, "%s:%d function %s uses register %s (wasUsed: %d, %p)\n",
3545 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3546 pic16_regWithIdx(i)->name,
3547 pic16_regWithIdx(i)->wasUsed,
3548 pic16_regWithIdx(i));
3551 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3553 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3554 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3555 // &pic16_pc_postdec1, 0));
3559 if(!pic16_regWithIdx(i)->wasUsed) {
3560 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3561 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3563 pic16_regWithIdx(i)->wasUsed = 1;
3575 if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3577 if (options.useXstack) {
3578 pic16_emitcode("mov","r0,%s",spname);
3579 pic16_emitcode("mov","a,_bp");
3580 pic16_emitcode("movx","@r0,a");
3581 pic16_emitcode("inc","%s",spname);
3583 /* set up the stack */
3584 pic16_emitcode ("push","_bp"); /* save the callers stack */
3586 pic16_emitcode ("mov","_bp,%s",spname);
3589 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3591 /* adjust the stack for the function */
3596 werror(W_STACK_OVERFLOW,sym->name);
3598 if (i > 3 && sym->recvSize < 4) {
3599 pic16_emitcode ("mov","a,sp");
3600 pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3601 pic16_emitcode ("mov","sp,a");
3604 pic16_emitcode("inc","sp");
3608 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3610 pic16_emitcode ("mov","a,_spx");
3611 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3612 pic16_emitcode ("mov","_spx,a");
3617 /*-----------------------------------------------------------------*/
3618 /* genEndFunction - generates epilogue for functions */
3619 /*-----------------------------------------------------------------*/
3620 static void genEndFunction (iCode *ic)
3622 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3624 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3626 if(IFFUNC_ISNAKED(sym->type)) {
3627 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3631 /* add code for ISCRITICAL */
3634 if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3636 pic16_emitcode ("mov","%s,_bp",spname);
3640 /* if use external stack but some variables were
3641 added to the local stack then decrement the
3643 if (options.useXstack && sym->stack) {
3644 pic16_emitcode("mov","a,sp");
3645 pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3646 pic16_emitcode("mov","sp,a");
3651 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3652 if (options.useXstack) {
3653 pic16_emitcode("mov","r0,%s",spname);
3654 pic16_emitcode("movx","a,@r0");
3655 pic16_emitcode("mov","_bp,a");
3656 pic16_emitcode("dec","%s",spname);
3660 pic16_emitcode ("pop","_bp");
3665 if (IFFUNC_ISISR(sym->type)) {
3666 /* now we need to restore the registers */
3667 /* if any registers used */
3668 if (sym->regsUsed) {
3671 /* restore registers used */
3672 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3673 for ( i = sym->regsUsed->size; i >= 0; i--) {
3674 if (bitVectBitValue(sym->regsUsed,i)) {
3676 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3677 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3678 // pic16_regWithIdx(i)->name);
3680 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3682 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3683 // &pic16_pc_preinc1,
3684 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3690 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3691 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3692 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3693 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3695 if(!(_G.interruptvector == 1)) {
3696 /* do not restore interrupt vector for WREG,STATUS,BSR
3697 * for high priority interrupt, see genFunction */
3699 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3700 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3701 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3704 _G.interruptvector = 0; /* sanity check */
3706 // pic16_pBlockConvert2ISR(pb);
3709 /* if debug then send end of function */
3710 /* if (options.debug && currFunc) */
3712 debugFile->writeEndFunction (currFunc, ic, 1);
3715 pic16_emitpcodeNULLop(POC_RETFIE);
3717 if (IFFUNC_ISCRITICAL(sym->type))
3718 pic16_emitcode("setb","ea");
3721 // pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3723 /* if any registers used */
3724 if (sym->regsUsed) {
3726 /* save the registers used */
3727 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3728 for ( i = sym->regsUsed->size; i >= 0; i--) {
3729 if (bitVectBitValue(sym->regsUsed,i)) {
3731 // fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3732 // __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3733 // pic16_regWithIdx(i)->name);
3735 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3737 // pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3738 // &pic16_pc_preinc1,
3739 // PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3746 // pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3747 /* if debug then send end of function */
3749 debugFile->writeEndFunction (currFunc, ic, 1);
3752 /* insert code to restore stack frame, if user enabled it
3753 * and function is not main() */
3756 if(strcmp(sym->name, "main")) {
3757 if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3758 /* restore stack frame */
3759 if(STACK_MODEL_LARGE)
3760 pic16_emitpcode(POC_MOVFF,
3761 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3762 pic16_emitpcode(POC_MOVFF,
3763 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3767 pic16_emitcode ("return","");
3768 pic16_emitpcodeNULLop(POC_RETURN);
3770 /* Mark the end of a function */
3771 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3777 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3781 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3783 if(dest->type != PO_WREG)
3784 pic16_emitpcode(POC_MOVWF, dest);
3786 if(dest->type == PO_WREG && (offset == 0)) {
3787 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3791 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3792 pic16_popGet(AOP(op), offset), dest));
3796 /*-----------------------------------------------------------------*/
3797 /* genRet - generate code for return statement */
3798 /*-----------------------------------------------------------------*/
3799 static void genRet (iCode *ic)
3804 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3805 /* if we have no return value then
3806 * just generate the "ret" */
3811 /* we have something to return then
3812 * move the return value into place */
3813 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3814 size = AOP_SIZE(IC_LEFT(ic));
3818 pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3819 // pic16_emitpcode(POC_MOVFF,
3820 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3823 pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3824 // pic16_emitpcode(POC_MOVFF,
3825 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3828 pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3829 // pic16_emitpcode(POC_MOVFF,
3830 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3833 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12
3835 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12
3836 // pic16_emitpcode(POC_MOVFF,
3837 // pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3840 /* >32-bits, setup stack and FSR0 */
3842 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3843 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3845 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3847 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3852 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3853 pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3855 if(STACK_MODEL_LARGE) {
3856 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3857 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3859 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3864 /* old code, left here for reference -- VR */
3868 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3870 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3871 pic16_emitpcomment("push %s",l);
3874 DEBUGpic16_emitcode(";", "%d", __LINE__);
3875 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3876 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3878 if (strcmp(fReturn[offset],l)) {
3879 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3880 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3881 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3883 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3887 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3897 if (strcmp(fReturn[pushed],"a"))
3898 pic16_emitcode("pop",fReturn[pushed]);
3900 pic16_emitcode("pop","acc");
3906 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3909 /* generate a jump to the return label
3910 * if the next is not the return statement */
3911 if (!(ic->next && ic->next->op == LABEL
3912 && IC_LABEL(ic->next) == returnLabel)) {
3914 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3915 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3919 /*-----------------------------------------------------------------*/
3920 /* genLabel - generates a label */
3921 /*-----------------------------------------------------------------*/
3922 static void genLabel (iCode *ic)
3926 /* special case never generate */
3927 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3928 if (IC_LABEL(ic) == entryLabel)
3931 pic16_emitpLabel(IC_LABEL(ic)->key);
3932 pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3935 /*-----------------------------------------------------------------*/
3936 /* genGoto - generates a goto */
3937 /*-----------------------------------------------------------------*/
3939 static void genGoto (iCode *ic)
3941 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3942 pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3946 /*-----------------------------------------------------------------*/
3947 /* genMultbits :- multiplication of bits */
3948 /*-----------------------------------------------------------------*/
3949 static void genMultbits (operand *left,
3953 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3955 if(!pic16_sameRegs(AOP(result),AOP(right)))
3956 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
3958 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3959 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3960 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
3965 /*-----------------------------------------------------------------*/
3966 /* genMultOneByte : 8 bit multiplication & division */
3967 /*-----------------------------------------------------------------*/
3968 static void genMultOneByte (operand *left,
3973 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3974 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3975 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3977 /* (if two literals, the value is computed before) */
3978 /* if one literal, literal on the right */
3979 if (AOP_TYPE(left) == AOP_LIT){
3985 /* size is already checked in genMult == 1 */
3986 // size = AOP_SIZE(result);
3988 if (AOP_TYPE(right) == AOP_LIT){
3989 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3990 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3991 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3992 pic16_aopGet(AOP(result),0,FALSE,FALSE));
3994 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3995 pic16_aopGet(AOP(right),0,FALSE,FALSE),
3996 pic16_aopGet(AOP(left),0,FALSE,FALSE),
3997 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4000 pic16_genMult8X8_8 (left, right,result);
4003 /*-----------------------------------------------------------------*/
4004 /* genMultOneWord : 16 bit multiplication */
4005 /*-----------------------------------------------------------------*/
4006 static void genMultOneWord (operand *left,
4011 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4012 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4013 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4015 /* (if two literals, the value is computed before)
4016 * if one literal, literal on the right */
4017 if (AOP_TYPE(left) == AOP_LIT){
4023 /* size is checked already == 2 */
4024 // size = AOP_SIZE(result);
4026 if (AOP_TYPE(right) == AOP_LIT) {
4027 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4028 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4029 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4030 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4032 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4033 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4034 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4035 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4038 pic16_genMult16X16_16(left, right,result);
4041 /*-----------------------------------------------------------------*/
4042 /* genMultOneLong : 32 bit multiplication */
4043 /*-----------------------------------------------------------------*/
4044 static void genMultOneLong (operand *left,
4049 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4050 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4051 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4053 /* (if two literals, the value is computed before)
4054 * if one literal, literal on the right */
4055 if (AOP_TYPE(left) == AOP_LIT){
4061 /* size is checked already == 4 */
4062 // size = AOP_SIZE(result);
4064 if (AOP_TYPE(right) == AOP_LIT) {
4065 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4066 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4067 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4068 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4070 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4071 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4072 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4073 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4076 pic16_genMult32X32_32(left, right,result);
4081 /*-----------------------------------------------------------------*/
4082 /* genMult - generates code for multiplication */
4083 /*-----------------------------------------------------------------*/
4084 static void genMult (iCode *ic)
4086 operand *left = IC_LEFT(ic);
4087 operand *right = IC_RIGHT(ic);
4088 operand *result= IC_RESULT(ic);
4090 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4091 /* assign the amsops */
4092 pic16_aopOp (left,ic,FALSE);
4093 pic16_aopOp (right,ic,FALSE);
4094 pic16_aopOp (result,ic,TRUE);
4096 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4098 /* special cases first *
4100 if (AOP_TYPE(left) == AOP_CRY
4101 && AOP_TYPE(right)== AOP_CRY) {
4102 genMultbits(left,right,result);
4106 /* if both are of size == 1 */
4107 if(AOP_SIZE(left) == 1
4108 && AOP_SIZE(right) == 1) {
4109 genMultOneByte(left,right,result);
4113 /* if both are of size == 2 */
4114 if(AOP_SIZE(left) == 2
4115 && AOP_SIZE(right) == 2) {
4116 genMultOneWord(left, right, result);
4120 /* if both are of size == 4 */
4121 if(AOP_SIZE(left) == 4
4122 && AOP_SIZE(right) == 4) {
4123 genMultOneLong(left, right, result);
4127 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4130 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4131 /* should have been converted to function call */
4135 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4136 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4137 pic16_freeAsmop(result,NULL,ic,TRUE);
4140 /*-----------------------------------------------------------------*/
4141 /* genDivbits :- division of bits */
4142 /*-----------------------------------------------------------------*/
4143 static void genDivbits (operand *left,
4150 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4151 /* the result must be bit */
4152 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4153 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4157 pic16_emitcode("div","ab");
4158 pic16_emitcode("rrc","a");
4159 pic16_aopPut(AOP(result),"c",0);
4162 /*-----------------------------------------------------------------*/
4163 /* genDivOneByte : 8 bit division */
4164 /*-----------------------------------------------------------------*/
4165 static void genDivOneByte (operand *left,
4169 sym_link *opetype = operandType(result);
4174 /* result = divident / divisor
4175 * - divident may be a register or a literal,
4176 * - divisor may be a register or a literal,
4177 * so there are 3 cases (literal / literal is optimized
4178 * by the front-end) to handle.
4179 * In addition we must handle signed and unsigned, which
4180 * result in 6 final different cases -- VR */
4182 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4183 size = AOP_SIZE(result) - 1;
4185 /* signed or unsigned */
4186 if (SPEC_USIGN(opetype)) {
4187 pCodeOp *pct1, /* count */
4190 symbol *label1, *label2, *label3;;
4193 /* unsigned is easy */
4195 pct1 = pic16_popGetTempReg();
4196 pct2 = pic16_popGetTempReg();
4197 pct3 = pic16_popGetTempReg();
4199 label1 = newiTempLabel(NULL);
4200 label2 = newiTempLabel(NULL);
4201 label3 = newiTempLabel(NULL);
4203 /* the following algorithm is extracted from divuint.c */
4205 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4206 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4208 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4210 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4212 pic16_emitpLabel(label1->key);
4215 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4219 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4223 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4225 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4226 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4228 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4229 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4230 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4232 pic16_emitpLabel( label3->key );
4233 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4234 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4238 pic16_emitpLabel(label2->key);
4239 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4240 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4241 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4243 /* result is in wreg */
4244 if(AOP_TYPE(result) != AOP_ACC)
4245 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4247 pic16_popReleaseTempReg( pct3 );
4248 pic16_popReleaseTempReg( pct2 );
4249 pic16_popReleaseTempReg( pct1 );
4254 /* signed is a little bit more difficult */
4256 /* save the signs of the operands */
4257 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4259 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4260 pic16_emitcode("push","acc"); /* save it on the stack */
4262 /* now sign adjust for both left & right */
4263 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4265 lbl = newiTempLabel(NULL);
4266 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4267 pic16_emitcode("cpl","a");
4268 pic16_emitcode("inc","a");
4269 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4270 pic16_emitcode("mov","b,a");
4272 /* sign adjust left side */
4273 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4276 lbl = newiTempLabel(NULL);
4277 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4278 pic16_emitcode("cpl","a");
4279 pic16_emitcode("inc","a");
4280 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4282 /* now the division */
4283 pic16_emitcode("div","ab");
4284 /* we are interested in the lower order
4286 pic16_emitcode("mov","b,a");
4287 lbl = newiTempLabel(NULL);
4288 pic16_emitcode("pop","acc");
4289 /* if there was an over flow we don't
4290 adjust the sign of the result */
4291 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4292 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4294 pic16_emitcode("clr","a");
4295 pic16_emitcode("subb","a,b");
4296 pic16_emitcode("mov","b,a");
4297 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4299 /* now we are done */
4300 pic16_aopPut(AOP(result),"b",0);
4302 pic16_emitcode("mov","c,b.7");
4303 pic16_emitcode("subb","a,acc");
4306 pic16_aopPut(AOP(result),"a",offset++);
4310 /*-----------------------------------------------------------------*/
4311 /* genDiv - generates code for division */
4312 /*-----------------------------------------------------------------*/
4313 static void genDiv (iCode *ic)
4315 operand *left = IC_LEFT(ic);
4316 operand *right = IC_RIGHT(ic);
4317 operand *result= IC_RESULT(ic);
4320 /* Division is a very lengthy algorithm, so it is better
4321 * to call support routines than inlining algorithm.
4322 * Division functions written here just in case someone
4323 * wants to inline and not use the support libraries -- VR */
4325 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4326 /* assign the amsops */
4327 pic16_aopOp (left,ic,FALSE);
4328 pic16_aopOp (right,ic,FALSE);
4329 pic16_aopOp (result,ic,TRUE);
4331 /* special cases first */
4333 if (AOP_TYPE(left) == AOP_CRY &&
4334 AOP_TYPE(right)== AOP_CRY) {
4335 genDivbits(left,right,result);
4339 /* if both are of size == 1 */
4340 if (AOP_SIZE(left) == 1 &&
4341 AOP_SIZE(right) == 1 ) {
4342 genDivOneByte(left,right,result);
4346 /* should have been converted to function call */
4349 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4350 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4351 pic16_freeAsmop(result,NULL,ic,TRUE);
4354 /*-----------------------------------------------------------------*/
4355 /* genModbits :- modulus of bits */
4356 /*-----------------------------------------------------------------*/
4357 static void genModbits (operand *left,
4364 /* the result must be bit */
4365 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4366 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4370 pic16_emitcode("div","ab");
4371 pic16_emitcode("mov","a,b");
4372 pic16_emitcode("rrc","a");
4373 pic16_aopPut(AOP(result),"c",0);
4376 /*-----------------------------------------------------------------*/
4377 /* genModOneByte : 8 bit modulus */
4378 /*-----------------------------------------------------------------*/
4379 static void genModOneByte (operand *left,
4383 sym_link *opetype = operandType(result);
4387 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4388 /* signed or unsigned */
4389 if (SPEC_USIGN(opetype)) {
4390 /* unsigned is easy */
4391 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4392 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4394 pic16_emitcode("div","ab");
4395 pic16_aopPut(AOP(result),"b",0);
4399 /* signed is a little bit more difficult */
4401 /* save the signs of the operands */
4402 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4405 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4406 pic16_emitcode("push","acc"); /* save it on the stack */
4408 /* now sign adjust for both left & right */
4409 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4412 lbl = newiTempLabel(NULL);
4413 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4414 pic16_emitcode("cpl","a");
4415 pic16_emitcode("inc","a");
4416 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4417 pic16_emitcode("mov","b,a");
4419 /* sign adjust left side */
4420 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4423 lbl = newiTempLabel(NULL);
4424 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4425 pic16_emitcode("cpl","a");
4426 pic16_emitcode("inc","a");
4427 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4429 /* now the multiplication */
4430 pic16_emitcode("div","ab");
4431 /* we are interested in the lower order
4433 lbl = newiTempLabel(NULL);
4434 pic16_emitcode("pop","acc");
4435 /* if there was an over flow we don't
4436 adjust the sign of the result */
4437 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4438 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4440 pic16_emitcode("clr","a");
4441 pic16_emitcode("subb","a,b");
4442 pic16_emitcode("mov","b,a");
4443 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4445 /* now we are done */
4446 pic16_aopPut(AOP(result),"b",0);
4450 /*-----------------------------------------------------------------*/
4451 /* genMod - generates code for division */
4452 /*-----------------------------------------------------------------*/
4453 static void genMod (iCode *ic)
4455 operand *left = IC_LEFT(ic);
4456 operand *right = IC_RIGHT(ic);
4457 operand *result= IC_RESULT(ic);
4459 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4460 /* assign the amsops */
4461 pic16_aopOp (left,ic,FALSE);
4462 pic16_aopOp (right,ic,FALSE);
4463 pic16_aopOp (result,ic,TRUE);
4465 /* special cases first */
4467 if (AOP_TYPE(left) == AOP_CRY &&
4468 AOP_TYPE(right)== AOP_CRY) {
4469 genModbits(left,right,result);
4473 /* if both are of size == 1 */
4474 if (AOP_SIZE(left) == 1 &&
4475 AOP_SIZE(right) == 1 ) {
4476 genModOneByte(left,right,result);
4480 /* should have been converted to function call */
4484 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4485 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4486 pic16_freeAsmop(result,NULL,ic,TRUE);
4489 /*-----------------------------------------------------------------*/
4490 /* genIfxJump :- will create a jump depending on the ifx */
4491 /*-----------------------------------------------------------------*/
4493 note: May need to add parameter to indicate when a variable is in bit space.
4495 static void genIfxJump (iCode *ic, char *jval)
4498 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4499 /* if true label then we jump if condition
4501 if ( IC_TRUE(ic) ) {
4503 if(strcmp(jval,"a") == 0)
4505 else if (strcmp(jval,"c") == 0)
4508 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4509 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4512 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4513 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4517 /* false label is present */
4518 if(strcmp(jval,"a") == 0)
4520 else if (strcmp(jval,"c") == 0)
4523 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4524 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4527 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4528 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4533 /* mark the icode as generated */
4540 /*-----------------------------------------------------------------*/
4542 /*-----------------------------------------------------------------*/
4543 static void genSkip(iCode *ifx,int status_bit)
4545 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4549 if ( IC_TRUE(ifx) ) {
4550 switch(status_bit) {
4565 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4566 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4570 switch(status_bit) {
4584 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4585 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4592 /*-----------------------------------------------------------------*/
4594 /*-----------------------------------------------------------------*/
4595 static void genSkipc(resolvedIfx *rifx)
4597 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4607 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4608 rifx->generated = 1;
4611 /*-----------------------------------------------------------------*/
4613 /*-----------------------------------------------------------------*/
4614 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4616 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4621 if( (rifx->condition ^ invert_condition) & 1)
4626 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4627 rifx->generated = 1;
4631 /*-----------------------------------------------------------------*/
4633 /*-----------------------------------------------------------------*/
4634 static void genSkipz(iCode *ifx, int condition)
4645 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4647 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4650 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4652 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4657 /*-----------------------------------------------------------------*/
4659 /*-----------------------------------------------------------------*/
4660 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4666 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4668 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4671 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4672 rifx->generated = 1;
4676 /*-----------------------------------------------------------------*/
4677 /* genChkZeroes :- greater or less than comparison */
4678 /* For each byte in a literal that is zero, inclusive or the */
4679 /* the corresponding byte in the operand with W */
4680 /* returns true if any of the bytes are zero */
4681 /*-----------------------------------------------------------------*/
4682 static int genChkZeroes(operand *op, int lit, int size)
4689 i = (lit >> (size*8)) & 0xff;
4693 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4695 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4704 /*-----------------------------------------------------------------*/
4705 /* genCmp :- greater or less than comparison */
4706 /*-----------------------------------------------------------------*/
4707 static void genCmp (operand *left,operand *right,
4708 operand *result, iCode *ifx, int sign)
4710 int size; //, offset = 0 ;
4711 unsigned long lit = 0L,i = 0;
4712 resolvedIfx rFalseIfx;
4713 // resolvedIfx rTrueIfx;
4715 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4718 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4719 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4723 resolveIfx(&rFalseIfx,ifx);
4724 truelbl = newiTempLabel(NULL);
4725 size = max(AOP_SIZE(left),AOP_SIZE(right));
4727 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4731 /* if literal is on the right then swap with left */
4732 if ((AOP_TYPE(right) == AOP_LIT)) {
4733 operand *tmp = right ;
4734 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4735 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4738 lit = (lit - 1) & mask;
4741 rFalseIfx.condition ^= 1;
4744 } else if ((AOP_TYPE(left) == AOP_LIT)) {
4745 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4749 //if(IC_TRUE(ifx) == NULL)
4750 /* if left & right are bit variables */
4751 if (AOP_TYPE(left) == AOP_CRY &&
4752 AOP_TYPE(right) == AOP_CRY ) {
4753 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4754 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4756 /* subtract right from left if at the
4757 end the carry flag is set then we know that
4758 left is greater than right */
4760 symbol *lbl = newiTempLabel(NULL);
4763 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4764 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4768 if(AOP_TYPE(right) == AOP_LIT) {
4770 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4772 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4779 genSkipCond(&rFalseIfx,left,size-1,7);
4781 /* no need to compare to 0...*/
4782 /* NOTE: this is a de-generate compare that most certainly
4783 * creates some dead code. */
4784 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4786 if(ifx) ifx->generated = 1;
4793 //i = (lit >> (size*8)) & 0xff;
4794 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4796 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4798 i = ((0-lit) & 0xff);
4801 /* lit is 0x7f, all signed chars are less than
4802 * this except for 0x7f itself */
4803 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4804 genSkipz2(&rFalseIfx,0);
4806 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4807 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4808 genSkipc(&rFalseIfx);
4813 genSkipz2(&rFalseIfx,1);
4815 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4816 genSkipc(&rFalseIfx);
4820 if(ifx) ifx->generated = 1;
4824 /* chars are out of the way. now do ints and longs */
4827 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4834 genSkipCond(&rFalseIfx,left,size,7);
4835 if(ifx) ifx->generated = 1;
4840 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4842 //rFalseIfx.condition ^= 1;
4843 //genSkipCond(&rFalseIfx,left,size,7);
4844 //rFalseIfx.condition ^= 1;
4846 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4847 if(rFalseIfx.condition)
4848 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4850 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4852 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4853 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4854 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4857 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4859 if(rFalseIfx.condition) {
4861 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4867 genSkipc(&rFalseIfx);
4868 pic16_emitpLabel(truelbl->key);
4869 if(ifx) ifx->generated = 1;
4876 if( (lit & 0xff) == 0) {
4877 /* lower byte is zero */
4878 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4879 i = ((lit >> 8) & 0xff) ^0x80;
4880 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4881 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4882 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4883 genSkipc(&rFalseIfx);
4886 if(ifx) ifx->generated = 1;
4891 /* Special cases for signed longs */
4892 if( (lit & 0xffffff) == 0) {
4893 /* lower byte is zero */
4894 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4895 i = ((lit >> 8*3) & 0xff) ^0x80;
4896 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4897 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4898 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4899 genSkipc(&rFalseIfx);
4902 if(ifx) ifx->generated = 1;
4910 if(lit & (0x80 << (size*8))) {
4911 /* lit is negative */
4912 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4914 //genSkipCond(&rFalseIfx,left,size,7);
4916 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4918 if(rFalseIfx.condition)
4919 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4921 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
4925 /* lit is positive */
4926 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4927 pic16_emitpcode(POC_BTFSC, 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(rFalseIfx.lbl->key));
4931 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
4936 This works, but is only good for ints.
4937 It also requires a "known zero" register.
4938 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4939 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4940 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
4941 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4942 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4943 genSkipc(&rFalseIfx);
4945 pic16_emitpLabel(truelbl->key);
4946 if(ifx) ifx->generated = 1;
4950 /* There are no more special cases, so perform a general compare */
4952 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4953 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4957 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4959 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4961 //rFalseIfx.condition ^= 1;
4962 genSkipc(&rFalseIfx);
4964 pic16_emitpLabel(truelbl->key);
4966 if(ifx) ifx->generated = 1;
4973 /* sign is out of the way. So now do an unsigned compare */
4974 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4977 /* General case - compare to an unsigned literal on the right.*/
4979 i = (lit >> (size*8)) & 0xff;
4980 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4981 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4983 i = (lit >> (size*8)) & 0xff;
4986 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4988 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4990 /* this byte of the lit is zero,
4991 *if it's not the last then OR in the variable */
4993 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4998 pic16_emitpLabel(lbl->key);
4999 // pic16_emitpLabel(truelbl->key);
5000 //if(emitFinalCheck)
5001 genSkipc(&rFalseIfx);
5003 pic16_emitpLabel(truelbl->key);
5005 if(ifx) ifx->generated = 1;
5012 if(AOP_TYPE(left) == AOP_LIT) {
5013 //symbol *lbl = newiTempLabel(NULL);
5015 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5018 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5021 if((lit == 0) && (sign == 0)){
5024 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5026 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5028 genSkipz2(&rFalseIfx,0);
5029 if(ifx) ifx->generated = 1;
5036 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5037 /* degenerate compare can never be true */
5038 if(rFalseIfx.condition == 0)
5039 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5041 if(ifx) ifx->generated = 1;
5046 /* signed comparisons to a literal byte */
5048 int lp1 = (lit+1) & 0xff;
5050 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5053 rFalseIfx.condition ^= 1;
5054 genSkipCond(&rFalseIfx,right,0,7);
5057 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5058 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5059 genSkipz2(&rFalseIfx,1);
5062 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5063 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5064 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5065 rFalseIfx.condition ^= 1;
5066 genSkipc(&rFalseIfx);
5070 /* unsigned comparisons to a literal byte */
5072 switch(lit & 0xff ) {
5074 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5075 genSkipz2(&rFalseIfx,0);
5078 rFalseIfx.condition ^= 1;
5079 genSkipCond(&rFalseIfx,right,0,7);
5083 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5084 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5085 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5086 rFalseIfx.condition ^= 1;
5087 if (AOP_TYPE(result) == AOP_CRY)
5088 genSkipc(&rFalseIfx);
5090 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5091 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5097 if(ifx) ifx->generated = 1;
5098 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5104 /* Size is greater than 1 */
5112 /* this means lit = 0xffffffff, or -1 */
5115 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5116 rFalseIfx.condition ^= 1;
5117 genSkipCond(&rFalseIfx,right,size,7);
5118 if(ifx) ifx->generated = 1;
5125 if(rFalseIfx.condition) {
5126 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5127 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5130 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5132 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5136 if(rFalseIfx.condition) {
5137 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5138 pic16_emitpLabel(truelbl->key);
5140 rFalseIfx.condition ^= 1;
5141 genSkipCond(&rFalseIfx,right,s,7);
5144 if(ifx) ifx->generated = 1;
5148 if((size == 1) && (0 == (lp1&0xff))) {
5149 /* lower byte of signed word is zero */
5150 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5151 i = ((lp1 >> 8) & 0xff) ^0x80;
5152 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5153 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5154 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5155 rFalseIfx.condition ^= 1;
5156 genSkipc(&rFalseIfx);
5159 if(ifx) ifx->generated = 1;
5163 if(lit & (0x80 << (size*8))) {
5164 /* Lit is less than zero */
5165 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5166 //rFalseIfx.condition ^= 1;
5167 //genSkipCond(&rFalseIfx,left,size,7);
5168 //rFalseIfx.condition ^= 1;
5169 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5170 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5172 if(rFalseIfx.condition)
5173 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5175 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5179 /* Lit is greater than or equal to zero */
5180 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5181 //rFalseIfx.condition ^= 1;
5182 //genSkipCond(&rFalseIfx,right,size,7);
5183 //rFalseIfx.condition ^= 1;
5185 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5186 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5188 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5189 if(rFalseIfx.condition)
5190 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5192 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5197 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5198 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5202 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5204 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5206 rFalseIfx.condition ^= 1;
5207 //rFalseIfx.condition = 1;
5208 genSkipc(&rFalseIfx);
5210 pic16_emitpLabel(truelbl->key);
5212 if(ifx) ifx->generated = 1;
5217 /* compare word or long to an unsigned literal on the right.*/
5222 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5225 break; /* handled above */
5228 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5230 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5231 genSkipz2(&rFalseIfx,0);
5235 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5237 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5240 if(rFalseIfx.condition)
5241 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5243 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5246 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5247 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5249 rFalseIfx.condition ^= 1;
5250 genSkipc(&rFalseIfx);
5253 pic16_emitpLabel(truelbl->key);
5255 if(ifx) ifx->generated = 1;
5261 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5262 i = (lit >> (size*8)) & 0xff;
5264 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5265 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5268 i = (lit >> (size*8)) & 0xff;
5271 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5273 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5275 /* this byte of the lit is zero,
5276 * if it's not the last then OR in the variable */
5278 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5283 pic16_emitpLabel(lbl->key);
5285 rFalseIfx.condition ^= 1;
5287 genSkipc(&rFalseIfx);
5291 pic16_emitpLabel(truelbl->key);
5292 if(ifx) ifx->generated = 1;
5296 /* Compare two variables */
5298 DEBUGpic16_emitcode(";sign","%d",sign);
5302 /* Sigh. thus sucks... */
5306 pctemp = pic16_popGetTempReg();
5307 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5308 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5309 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5310 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5311 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5312 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5313 pic16_popReleaseTempReg(pctemp);
5315 /* Signed char comparison */
5316 /* Special thanks to Nikolai Golovchenko for this snippet */
5317 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5318 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5319 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5320 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5321 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5322 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5324 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5325 genSkipc(&rFalseIfx);
5327 if(ifx) ifx->generated = 1;
5333 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5334 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5338 /* The rest of the bytes of a multi-byte compare */
5342 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5345 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5346 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5351 pic16_emitpLabel(lbl->key);
5353 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5354 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5355 (AOP_TYPE(result) == AOP_REG)) {
5356 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5357 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5359 genSkipc(&rFalseIfx);
5361 //genSkipc(&rFalseIfx);
5362 if(ifx) ifx->generated = 1;
5369 if ((AOP_TYPE(result) != AOP_CRY)
5370 && AOP_SIZE(result)) {
5371 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5373 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5375 pic16_outBitC(result);
5377 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5378 /* if the result is used in the next
5379 ifx conditional branch then generate
5380 code a little differently */
5382 genIfxJump (ifx,"c");
5384 pic16_outBitC(result);
5385 /* leave the result in acc */
5390 /*-----------------------------------------------------------------*/
5391 /* genCmpGt :- greater than comparison */
5392 /*-----------------------------------------------------------------*/
5393 static void genCmpGt (iCode *ic, iCode *ifx)
5395 operand *left, *right, *result;
5396 sym_link *letype , *retype;
5399 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5401 right= IC_RIGHT(ic);
5402 result = IC_RESULT(ic);
5404 letype = getSpec(operandType(left));
5405 retype =getSpec(operandType(right));
5406 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5407 /* assign the amsops */
5408 pic16_aopOp (left,ic,FALSE);
5409 pic16_aopOp (right,ic,FALSE);
5410 pic16_aopOp (result,ic,TRUE);
5412 genCmp(right, left, result, ifx, sign);
5414 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5415 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5416 pic16_freeAsmop(result,NULL,ic,TRUE);
5419 /*-----------------------------------------------------------------*/
5420 /* genCmpLt - less than comparisons */
5421 /*-----------------------------------------------------------------*/
5422 static void genCmpLt (iCode *ic, iCode *ifx)
5424 operand *left, *right, *result;
5425 sym_link *letype , *retype;
5428 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5430 right= IC_RIGHT(ic);
5431 result = IC_RESULT(ic);
5433 letype = getSpec(operandType(left));
5434 retype =getSpec(operandType(right));
5435 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5437 /* assign the amsops */
5438 pic16_aopOp (left,ic,FALSE);
5439 pic16_aopOp (right,ic,FALSE);
5440 pic16_aopOp (result,ic,TRUE);
5442 genCmp(left, right, result, ifx, sign);
5444 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5445 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5446 pic16_freeAsmop(result,NULL,ic,TRUE);
5451 // FIXME reenable literal optimisation when the pic16 port is stable
5453 /*-----------------------------------------------------------------*/
5454 /* genc16bit2lit - compare a 16 bit value to a literal */
5455 /*-----------------------------------------------------------------*/
5456 static void genc16bit2lit(operand *op, int lit, int offset)
5460 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
5461 if( (lit&0xff) == 0)
5466 switch( BYTEofLONG(lit,i)) {
5468 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5471 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5474 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5477 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5478 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5483 switch( BYTEofLONG(lit,i)) {
5485 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5489 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5493 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5496 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5498 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5507 /*-----------------------------------------------------------------*/
5508 /* gencjneshort - compare and jump if not equal */
5509 /*-----------------------------------------------------------------*/
5510 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5512 int size = max(AOP_SIZE(left),AOP_SIZE(right));
5514 int res_offset = 0; /* the result may be a different size then left or right */
5515 int res_size = AOP_SIZE(result);
5517 symbol *lbl, *lbl_done;
5519 unsigned long lit = 0L;
5520 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5522 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5523 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5525 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
5526 resolveIfx(&rIfx,ifx);
5527 lbl = newiTempLabel(NULL);
5528 lbl_done = newiTempLabel(NULL);
5531 /* if the left side is a literal or
5532 if the right is in a pointer register and left
5534 if ((AOP_TYPE(left) == AOP_LIT) ||
5535 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5540 if(AOP_TYPE(right) == AOP_LIT)
5541 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5543 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5544 preserve_result = 1;
5546 if(result && !preserve_result)
5549 for(i = 0; i < AOP_SIZE(result); i++)
5550 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5554 /* if the right side is a literal then anything goes */
5555 if (AOP_TYPE(right) == AOP_LIT &&
5556 AOP_TYPE(left) != AOP_DIR ) {
5559 genc16bit2lit(left, lit, 0);
5561 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5564 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5567 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5568 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5570 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5574 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5576 if(res_offset < res_size-1)
5584 /* if the right side is in a register or in direct space or
5585 if the left is a pointer register & right is not */
5586 else if (AOP_TYPE(right) == AOP_REG ||
5587 AOP_TYPE(right) == AOP_DIR ||
5588 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5589 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5590 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5591 int lbl_key = lbl->key;
5594 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5595 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5597 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5598 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
5599 __FUNCTION__,__LINE__);
5603 /* switch(size) { */
5605 /* genc16bit2lit(left, lit, 0); */
5607 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5612 if((AOP_TYPE(left) == AOP_DIR) &&
5613 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5615 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5616 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5618 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5620 switch (lit & 0xff) {
5622 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5625 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5626 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5627 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5631 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5632 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5633 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5634 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5638 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5639 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5644 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5647 if(AOP_TYPE(result) == AOP_CRY) {
5648 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5653 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5655 /* fix me. probably need to check result size too */
5656 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5661 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5662 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5669 if(res_offset < res_size-1)
5674 } else if(AOP_TYPE(right) == AOP_REG &&
5675 AOP_TYPE(left) != AOP_DIR){
5678 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5679 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5680 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
5685 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5687 if(res_offset < res_size-1)
5692 /* right is a pointer reg need both a & b */
5694 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5696 pic16_emitcode("mov","b,%s",l);
5697 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5698 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
5703 if(result && preserve_result)
5706 for(i = 0; i < AOP_SIZE(result); i++)
5707 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5710 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5712 if(result && preserve_result)
5713 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5716 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5718 pic16_emitpLabel(lbl->key);
5720 if(result && preserve_result)
5723 for(i = 0; i < AOP_SIZE(result); i++)
5724 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5726 pic16_emitpLabel(lbl_done->key);
5729 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5737 /*-----------------------------------------------------------------*/
5738 /* gencjne - compare and jump if not equal */
5739 /*-----------------------------------------------------------------*/
5740 static void gencjne(operand *left, operand *right, iCode *ifx)
5742 symbol *tlbl = newiTempLabel(NULL);
5744 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5745 gencjneshort(left, right, lbl);
5747 pic16_emitcode("mov","a,%s",one);
5748 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5749 pic16_emitcode("","%05d_DS_:",lbl->key+100);
5750 pic16_emitcode("clr","a");
5751 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5753 pic16_emitpLabel(lbl->key);
5754 pic16_emitpLabel(tlbl->key);
5760 /*-----------------------------------------------------------------*/
5761 /* is_LitOp - check if operand has to be treated as literal */
5762 /*-----------------------------------------------------------------*/
5763 static bool is_LitOp(operand *op)
5765 return (AOP_TYPE(op) == AOP_LIT)
5766 || ( (AOP_TYPE(op) == AOP_PCODE)
5767 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5768 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));
5771 /*-----------------------------------------------------------------*/
5772 /* is_LitAOp - check if operand has to be treated as literal */
5773 /*-----------------------------------------------------------------*/
5774 static bool is_LitAOp(asmop *aop)
5776 return (aop->type == AOP_LIT)
5777 || ( (aop->type == AOP_PCODE)
5778 && ( (aop->aopu.pcop->type == PO_LITERAL)
5779 || (aop->aopu.pcop->type == PO_IMMEDIATE) ));
5784 /*-----------------------------------------------------------------*/
5785 /* genCmpEq - generates code for equal to */
5786 /*-----------------------------------------------------------------*/
5787 static void genCmpEq (iCode *ic, iCode *ifx)
5789 operand *left, *right, *result;
5790 symbol *falselbl = newiTempLabel(NULL);
5791 symbol *donelbl = newiTempLabel(NULL);
5793 int preserve_result = 0;
5794 int generate_result = 0;
5797 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5798 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5799 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5801 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5802 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5804 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5806 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
5807 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5811 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5813 operand *tmp = right ;
5818 if ( regsInCommon(left, result) || regsInCommon(right, result) )
5819 preserve_result = 1;
5821 if(result && AOP_SIZE(result))
5822 generate_result = 1;
5824 if(generate_result && !preserve_result)
5826 for(i = 0; i < AOP_SIZE(result); i++)
5827 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5830 for(i=0; i < AOP_SIZE(left); i++)
5832 if(AOP_TYPE(left) != AOP_ACC)
5835 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5837 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5840 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
5842 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
5844 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5849 if(generate_result && preserve_result)
5851 for(i = 0; i < AOP_SIZE(result); i++)
5852 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5856 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5858 if(generate_result && preserve_result)
5859 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5861 if(ifx && IC_TRUE(ifx))
5862 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5864 if(ifx && IC_FALSE(ifx))
5865 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5867 pic16_emitpLabel(falselbl->key);
5871 if(ifx && IC_FALSE(ifx))
5872 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5874 if(generate_result && preserve_result)
5876 for(i = 0; i < AOP_SIZE(result); i++)
5877 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5880 pic16_emitpLabel(donelbl->key);
5886 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5887 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5888 pic16_freeAsmop(result,NULL,ic,TRUE);
5894 // old version kept for reference
5896 /*-----------------------------------------------------------------*/
5897 /* genCmpEq - generates code for equal to */
5898 /*-----------------------------------------------------------------*/
5899 static void genCmpEq (iCode *ic, iCode *ifx)
5901 operand *left, *right, *result;
5902 unsigned long lit = 0L;
5904 symbol *falselbl = newiTempLabel(NULL);
5907 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5910 DEBUGpic16_emitcode ("; ifx is non-null","");
5912 DEBUGpic16_emitcode ("; ifx is null","");
5914 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5915 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5916 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5918 size = max(AOP_SIZE(left),AOP_SIZE(right));
5920 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5922 /* if literal, literal on the right or
5923 if the right is in a pointer register and left
5925 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
5926 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5927 operand *tmp = right ;
5933 if(ifx && !AOP_SIZE(result)){
5935 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
5936 /* if they are both bit variables */
5937 if (AOP_TYPE(left) == AOP_CRY &&
5938 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5939 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
5940 if(AOP_TYPE(right) == AOP_LIT){
5941 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5943 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5944 pic16_emitcode("cpl","c");
5945 } else if(lit == 1L) {
5946 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5948 pic16_emitcode("clr","c");
5950 /* AOP_TYPE(right) == AOP_CRY */
5952 symbol *lbl = newiTempLabel(NULL);
5953 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5954 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5955 pic16_emitcode("cpl","c");
5956 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5958 /* if true label then we jump if condition
5960 tlbl = newiTempLabel(NULL);
5961 if ( IC_TRUE(ifx) ) {
5962 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5963 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5965 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5966 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5968 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5971 /* left and right are both bit variables, result is carry */
5974 resolveIfx(&rIfx,ifx);
5976 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5977 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5978 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5979 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5984 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
5986 /* They're not both bit variables. Is the right a literal? */
5987 if(AOP_TYPE(right) == AOP_LIT) {
5988 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5993 switch(lit & 0xff) {
5995 if ( IC_TRUE(ifx) ) {
5996 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5998 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6000 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6001 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6005 if ( IC_TRUE(ifx) ) {
6006 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6008 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6010 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6011 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6015 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6017 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6022 /* end of size == 1 */
6026 genc16bit2lit(left,lit,offset);
6029 /* end of size == 2 */
6034 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6035 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6036 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6037 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6040 /* search for patterns that can be optimized */
6042 genc16bit2lit(left,lit,0);
6046 emitSKPZ; // if hi word unequal
6048 emitSKPNZ; // if hi word equal
6050 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6051 genc16bit2lit(left,lit,2);
6054 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6055 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6059 pic16_emitpLabel(falselbl->key);
6068 } else if(AOP_TYPE(right) == AOP_CRY ) {
6069 /* we know the left is not a bit, but that the right is */
6070 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6071 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6072 pic16_popGet(AOP(right),offset));
6073 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6075 /* if the two are equal, then W will be 0 and the Z bit is set
6076 * we could test Z now, or go ahead and check the high order bytes if
6077 * the variable we're comparing is larger than a byte. */
6080 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6082 if ( IC_TRUE(ifx) ) {
6084 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6085 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6088 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6089 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6093 /* They're both variables that are larger than bits */
6096 tlbl = newiTempLabel(NULL);
6099 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6100 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6102 if ( IC_TRUE(ifx) ) {
6106 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6108 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6109 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6113 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6116 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6117 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6122 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6124 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6125 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6129 if(s>1 && IC_TRUE(ifx)) {
6130 pic16_emitpLabel(tlbl->key);
6131 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6135 /* mark the icode as generated */
6140 /* if they are both bit variables */
6141 if (AOP_TYPE(left) == AOP_CRY &&
6142 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6143 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
6144 if(AOP_TYPE(right) == AOP_LIT){
6145 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6147 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6148 pic16_emitcode("cpl","c");
6149 } else if(lit == 1L) {
6150 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6152 pic16_emitcode("clr","c");
6154 /* AOP_TYPE(right) == AOP_CRY */
6156 symbol *lbl = newiTempLabel(NULL);
6157 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6158 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6159 pic16_emitcode("cpl","c");
6160 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6163 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6164 pic16_outBitC(result);
6168 genIfxJump (ifx,"c");
6171 /* if the result is used in an arithmetic operation
6172 then put the result in place */
6173 pic16_outBitC(result);
6176 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
6177 gencjne(left,right,result,ifx);
6180 gencjne(left,right,newiTempLabel(NULL));
6182 if(IC_TRUE(ifx)->key)
6183 gencjne(left,right,IC_TRUE(ifx)->key);
6185 gencjne(left,right,IC_FALSE(ifx)->key);
6189 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6190 pic16_aopPut(AOP(result),"a",0);
6195 genIfxJump (ifx,"a");
6199 /* if the result is used in an arithmetic operation
6200 then put the result in place */
6202 if (AOP_TYPE(result) != AOP_CRY)
6203 pic16_outAcc(result);
6205 /* leave the result in acc */
6209 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6210 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6211 pic16_freeAsmop(result,NULL,ic,TRUE);
6215 /*-----------------------------------------------------------------*/
6216 /* ifxForOp - returns the icode containing the ifx for operand */
6217 /*-----------------------------------------------------------------*/
6218 static iCode *ifxForOp ( operand *op, iCode *ic )
6220 /* if true symbol then needs to be assigned */
6221 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6222 if (IS_TRUE_SYMOP(op))
6225 /* if this has register type condition and
6226 the next instruction is ifx with the same operand
6227 and live to of the operand is upto the ifx only then */
6229 && ic->next->op == IFX
6230 && IC_COND(ic->next)->key == op->key
6231 && OP_SYMBOL(op)->liveTo <= ic->next->seq
6233 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6238 ic->next->op == IFX &&
6239 IC_COND(ic->next)->key == op->key) {
6240 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6244 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6246 ic->next->op == IFX)
6247 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6250 ic->next->op == IFX &&
6251 IC_COND(ic->next)->key == op->key) {
6252 DEBUGpic16_emitcode ("; "," key is okay");
6253 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6254 OP_SYMBOL(op)->liveTo,
6259 /* the code below is completely untested
6260 * it just allows ulong2fs.c compile -- VR */
6263 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6264 __FILE__, __FUNCTION__, __LINE__);
6266 /* if this has register type condition and
6267 the next instruction is ifx with the same operand
6268 and live to of the operand is upto the ifx only then */
6270 ic->next->op == IFX &&
6271 IC_COND(ic->next)->key == op->key &&
6272 OP_SYMBOL(op)->liveTo <= ic->next->seq )
6276 ic->next->op == IFX &&
6277 IC_COND(ic->next)->key == op->key) {
6278 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6282 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6283 __FILE__, __FUNCTION__, __LINE__);
6285 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
6290 /*-----------------------------------------------------------------*/
6291 /* genAndOp - for && operation */
6292 /*-----------------------------------------------------------------*/
6293 static void genAndOp (iCode *ic)
6295 operand *left,*right, *result;
6298 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6299 /* note here that && operations that are in an
6300 if statement are taken away by backPatchLabels
6301 only those used in arthmetic operations remain */
6302 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6303 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6304 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6306 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6308 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6309 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6310 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6312 /* if both are bit variables */
6313 /* if (AOP_TYPE(left) == AOP_CRY && */
6314 /* AOP_TYPE(right) == AOP_CRY ) { */
6315 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6316 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6317 /* pic16_outBitC(result); */
6319 /* tlbl = newiTempLabel(NULL); */
6320 /* pic16_toBoolean(left); */
6321 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6322 /* pic16_toBoolean(right); */
6323 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6324 /* pic16_outBitAcc(result); */
6327 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6328 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6329 pic16_freeAsmop(result,NULL,ic,TRUE);
6333 /*-----------------------------------------------------------------*/
6334 /* genOrOp - for || operation */
6335 /*-----------------------------------------------------------------*/
6338 modified this code, but it doesn't appear to ever get called
6341 static void genOrOp (iCode *ic)
6343 operand *left,*right, *result;
6346 /* note here that || operations that are in an
6347 if statement are taken away by backPatchLabels
6348 only those used in arthmetic operations remain */
6349 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6350 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6351 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6352 pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6354 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6356 /* if both are bit variables */
6357 if (AOP_TYPE(left) == AOP_CRY &&
6358 AOP_TYPE(right) == AOP_CRY ) {
6359 pic16_emitcode("clrc","");
6360 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6361 AOP(left)->aopu.aop_dir,
6362 AOP(left)->aopu.aop_dir);
6363 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6364 AOP(right)->aopu.aop_dir,
6365 AOP(right)->aopu.aop_dir);
6366 pic16_emitcode("setc","");
6369 tlbl = newiTempLabel(NULL);
6370 pic16_toBoolean(left);
6372 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6373 pic16_toBoolean(right);
6374 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6376 pic16_outBitAcc(result);
6379 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6380 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6381 pic16_freeAsmop(result,NULL,ic,TRUE);
6384 /*-----------------------------------------------------------------*/
6385 /* isLiteralBit - test if lit == 2^n */
6386 /*-----------------------------------------------------------------*/
6387 static int isLiteralBit(unsigned long lit)
6389 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6390 0x100L,0x200L,0x400L,0x800L,
6391 0x1000L,0x2000L,0x4000L,0x8000L,
6392 0x10000L,0x20000L,0x40000L,0x80000L,
6393 0x100000L,0x200000L,0x400000L,0x800000L,
6394 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6395 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6398 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6399 for(idx = 0; idx < 32; idx++)
6405 /*-----------------------------------------------------------------*/
6406 /* continueIfTrue - */
6407 /*-----------------------------------------------------------------*/
6408 static void continueIfTrue (iCode *ic)
6410 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6412 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6416 /*-----------------------------------------------------------------*/
6418 /*-----------------------------------------------------------------*/
6419 static void jumpIfTrue (iCode *ic)
6421 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6423 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6427 /*-----------------------------------------------------------------*/
6428 /* jmpTrueOrFalse - */
6429 /*-----------------------------------------------------------------*/
6430 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6432 // ugly but optimized by peephole
6433 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6435 symbol *nlbl = newiTempLabel(NULL);
6436 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
6437 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6438 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6439 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6442 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6443 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6448 /*-----------------------------------------------------------------*/
6449 /* genAnd - code for and */
6450 /*-----------------------------------------------------------------*/
6451 static void genAnd (iCode *ic, iCode *ifx)
6453 operand *left, *right, *result;
6455 unsigned long lit = 0L;
6460 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6461 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6462 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6463 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6465 resolveIfx(&rIfx,ifx);
6467 /* if left is a literal & right is not then exchange them */
6468 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6469 AOP_NEEDSACC(left)) {
6470 operand *tmp = right ;
6475 /* if result = right then exchange them */
6476 if(pic16_sameRegs(AOP(result),AOP(right))){
6477 operand *tmp = right ;
6482 /* if right is bit then exchange them */
6483 if (AOP_TYPE(right) == AOP_CRY &&
6484 AOP_TYPE(left) != AOP_CRY){
6485 operand *tmp = right ;
6489 if(AOP_TYPE(right) == AOP_LIT)
6490 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6492 size = AOP_SIZE(result);
6494 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6497 // result = bit & yy;
6498 if (AOP_TYPE(left) == AOP_CRY){
6499 // c = bit & literal;
6500 if(AOP_TYPE(right) == AOP_LIT){
6502 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6505 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6508 if(size && (AOP_TYPE(result) == AOP_CRY)){
6509 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6512 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6516 pic16_emitcode("clr","c");
6519 if (AOP_TYPE(right) == AOP_CRY){
6521 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6522 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6525 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6527 pic16_emitcode("rrc","a");
6528 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6534 pic16_outBitC(result);
6536 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6537 genIfxJump(ifx, "c");
6541 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6542 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6543 if((AOP_TYPE(right) == AOP_LIT) &&
6544 (AOP_TYPE(result) == AOP_CRY) &&
6545 (AOP_TYPE(left) != AOP_CRY)){
6546 int posbit = isLiteralBit(lit);
6550 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6553 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6559 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6560 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6562 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6563 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6566 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6567 size = AOP_SIZE(left);
6570 int bp = posbit, ofs=0;
6577 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6578 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
6582 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6583 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6585 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6592 symbol *tlbl = newiTempLabel(NULL);
6593 int sizel = AOP_SIZE(left);
6595 pic16_emitcode("setb","c");
6597 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6598 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6600 if((posbit = isLiteralBit(bytelit)) != 0)
6601 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6603 if(bytelit != 0x0FFL)
6604 pic16_emitcode("anl","a,%s",
6605 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6606 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6611 // bit = left & literal
6613 pic16_emitcode("clr","c");
6614 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6616 // if(left & literal)
6619 jmpTrueOrFalse(ifx, tlbl);
6623 pic16_outBitC(result);
6627 /* if left is same as result */
6628 if(pic16_sameRegs(AOP(result),AOP(left))){
6630 for(;size--; offset++,lit>>=8) {
6631 if(AOP_TYPE(right) == AOP_LIT){
6632 switch(lit & 0xff) {
6634 /* and'ing with 0 has clears the result */
6635 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6636 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6639 /* and'ing with 0xff is a nop when the result and left are the same */
6644 int p = my_powof2( (~lit) & 0xff );
6646 /* only one bit is set in the literal, so use a bcf instruction */
6647 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6648 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6651 pic16_emitcode("movlw","0x%x", (lit & 0xff));
6652 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6653 if(know_W != (lit&0xff))
6654 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6656 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6661 if (AOP_TYPE(left) == AOP_ACC) {
6662 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6664 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6665 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6672 // left & result in different registers
6673 if(AOP_TYPE(result) == AOP_CRY){
6675 // if(size), result in bit
6676 // if(!size && ifx), conditional oper: if(left & right)
6677 symbol *tlbl = newiTempLabel(NULL);
6678 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6680 pic16_emitcode("setb","c");
6682 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6683 pic16_emitcode("anl","a,%s",
6684 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6685 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6690 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6691 pic16_outBitC(result);
6693 jmpTrueOrFalse(ifx, tlbl);
6695 for(;(size--);offset++) {
6697 // result = left & right
6698 if(AOP_TYPE(right) == AOP_LIT){
6699 int t = (lit >> (offset*8)) & 0x0FFL;
6702 pic16_emitcode("clrf","%s",
6703 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6704 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6707 pic16_emitcode("movf","%s,w",
6708 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6709 pic16_emitcode("movwf","%s",
6710 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6711 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6712 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6715 pic16_emitcode("movlw","0x%x",t);
6716 pic16_emitcode("andwf","%s,w",
6717 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6718 pic16_emitcode("movwf","%s",
6719 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6721 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6722 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6723 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6728 if (AOP_TYPE(left) == AOP_ACC) {
6729 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6730 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6732 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6733 pic16_emitcode("andwf","%s,w",
6734 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6735 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6736 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6738 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6739 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6745 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6746 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6747 pic16_freeAsmop(result,NULL,ic,TRUE);
6750 /*-----------------------------------------------------------------*/
6751 /* genOr - code for or */
6752 /*-----------------------------------------------------------------*/
6753 static void genOr (iCode *ic, iCode *ifx)
6755 operand *left, *right, *result;
6757 unsigned long lit = 0L;
6759 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6761 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6762 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6763 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6765 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6767 /* if left is a literal & right is not then exchange them */
6768 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6769 AOP_NEEDSACC(left)) {
6770 operand *tmp = right ;
6775 /* if result = right then exchange them */
6776 if(pic16_sameRegs(AOP(result),AOP(right))){
6777 operand *tmp = right ;
6782 /* if right is bit then exchange them */
6783 if (AOP_TYPE(right) == AOP_CRY &&
6784 AOP_TYPE(left) != AOP_CRY){
6785 operand *tmp = right ;
6790 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6792 if(AOP_TYPE(right) == AOP_LIT)
6793 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6795 size = AOP_SIZE(result);
6799 if (AOP_TYPE(left) == AOP_CRY){
6800 if(AOP_TYPE(right) == AOP_LIT){
6801 // c = bit & literal;
6803 // lit != 0 => result = 1
6804 if(AOP_TYPE(result) == AOP_CRY){
6806 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6807 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6808 // AOP(result)->aopu.aop_dir,
6809 // AOP(result)->aopu.aop_dir);
6811 continueIfTrue(ifx);
6815 // lit == 0 => result = left
6816 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6818 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6821 if (AOP_TYPE(right) == AOP_CRY){
6822 if(pic16_sameRegs(AOP(result),AOP(left))){
6824 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6825 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6826 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6828 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6829 AOP(result)->aopu.aop_dir,
6830 AOP(result)->aopu.aop_dir);
6831 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6832 AOP(right)->aopu.aop_dir,
6833 AOP(right)->aopu.aop_dir);
6834 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6835 AOP(result)->aopu.aop_dir,
6836 AOP(result)->aopu.aop_dir);
6838 if( AOP_TYPE(result) == AOP_ACC) {
6839 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6840 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6841 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6842 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6846 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6847 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6848 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6849 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6851 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6852 AOP(result)->aopu.aop_dir,
6853 AOP(result)->aopu.aop_dir);
6854 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6855 AOP(right)->aopu.aop_dir,
6856 AOP(right)->aopu.aop_dir);
6857 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6858 AOP(left)->aopu.aop_dir,
6859 AOP(left)->aopu.aop_dir);
6860 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6861 AOP(result)->aopu.aop_dir,
6862 AOP(result)->aopu.aop_dir);
6867 symbol *tlbl = newiTempLabel(NULL);
6868 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6871 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
6872 if( AOP_TYPE(right) == AOP_ACC) {
6873 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6875 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6876 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6881 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6882 pic16_emitcode(";XXX setb","c");
6883 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6884 AOP(left)->aopu.aop_dir,tlbl->key+100);
6885 pic16_toBoolean(right);
6886 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6887 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6888 jmpTrueOrFalse(ifx, tlbl);
6892 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6899 pic16_outBitC(result);
6901 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6902 genIfxJump(ifx, "c");
6906 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6907 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6908 if((AOP_TYPE(right) == AOP_LIT) &&
6909 (AOP_TYPE(result) == AOP_CRY) &&
6910 (AOP_TYPE(left) != AOP_CRY)){
6912 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6915 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6917 continueIfTrue(ifx);
6920 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6921 // lit = 0, result = boolean(left)
6923 pic16_emitcode(";XXX setb","c");
6924 pic16_toBoolean(right);
6926 symbol *tlbl = newiTempLabel(NULL);
6927 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6929 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6931 genIfxJump (ifx,"a");
6935 pic16_outBitC(result);
6939 /* if left is same as result */
6940 if(pic16_sameRegs(AOP(result),AOP(left))){
6942 for(;size--; offset++,lit>>=8) {
6943 if(AOP_TYPE(right) == AOP_LIT){
6944 if((lit & 0xff) == 0)
6945 /* or'ing with 0 has no effect */
6948 int p = my_powof2(lit & 0xff);
6950 /* only one bit is set in the literal, so use a bsf instruction */
6951 pic16_emitpcode(POC_BSF,
6952 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6954 if(know_W != (lit & 0xff))
6955 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6956 know_W = lit & 0xff;
6957 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6962 if (AOP_TYPE(left) == AOP_ACC) {
6963 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
6964 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6966 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
6967 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6969 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6970 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6976 // left & result in different registers
6977 if(AOP_TYPE(result) == AOP_CRY){
6979 // if(size), result in bit
6980 // if(!size && ifx), conditional oper: if(left | right)
6981 symbol *tlbl = newiTempLabel(NULL);
6982 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6983 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6987 pic16_emitcode(";XXX setb","c");
6989 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6990 pic16_emitcode(";XXX orl","a,%s",
6991 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6992 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6997 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6998 pic16_outBitC(result);
7000 jmpTrueOrFalse(ifx, tlbl);
7001 } else for(;(size--);offset++){
7003 // result = left & right
7004 if(AOP_TYPE(right) == AOP_LIT){
7005 int t = (lit >> (offset*8)) & 0x0FFL;
7008 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7009 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7011 pic16_emitcode("movf","%s,w",
7012 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7013 pic16_emitcode("movwf","%s",
7014 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7017 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7018 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7019 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7021 pic16_emitcode("movlw","0x%x",t);
7022 pic16_emitcode("iorwf","%s,w",
7023 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7024 pic16_emitcode("movwf","%s",
7025 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7031 // faster than result <- left, anl result,right
7032 // and better if result is SFR
7033 if (AOP_TYPE(left) == AOP_ACC) {
7034 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7035 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7037 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7038 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7040 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7041 pic16_emitcode("iorwf","%s,w",
7042 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7044 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7045 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7050 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7051 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7052 pic16_freeAsmop(result,NULL,ic,TRUE);
7055 /*-----------------------------------------------------------------*/
7056 /* genXor - code for xclusive or */
7057 /*-----------------------------------------------------------------*/
7058 static void genXor (iCode *ic, iCode *ifx)
7060 operand *left, *right, *result;
7062 unsigned long lit = 0L;
7064 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7066 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7067 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7068 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7070 /* if left is a literal & right is not ||
7071 if left needs acc & right does not */
7072 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7073 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7074 operand *tmp = right ;
7079 /* if result = right then exchange them */
7080 if(pic16_sameRegs(AOP(result),AOP(right))){
7081 operand *tmp = right ;
7086 /* if right is bit then exchange them */
7087 if (AOP_TYPE(right) == AOP_CRY &&
7088 AOP_TYPE(left) != AOP_CRY){
7089 operand *tmp = right ;
7093 if(AOP_TYPE(right) == AOP_LIT)
7094 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7096 size = AOP_SIZE(result);
7100 if (AOP_TYPE(left) == AOP_CRY){
7101 if(AOP_TYPE(right) == AOP_LIT){
7102 // c = bit & literal;
7104 // lit>>1 != 0 => result = 1
7105 if(AOP_TYPE(result) == AOP_CRY){
7107 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
7108 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7110 continueIfTrue(ifx);
7113 pic16_emitcode("setb","c");
7117 // lit == 0, result = left
7118 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7120 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7122 // lit == 1, result = not(left)
7123 if(size && pic16_sameRegs(AOP(result),AOP(left))){
7124 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
7125 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
7126 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7129 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7130 pic16_emitcode("cpl","c");
7137 symbol *tlbl = newiTempLabel(NULL);
7138 if (AOP_TYPE(right) == AOP_CRY){
7140 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7143 int sizer = AOP_SIZE(right);
7145 // if val>>1 != 0, result = 1
7146 pic16_emitcode("setb","c");
7148 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7150 // test the msb of the lsb
7151 pic16_emitcode("anl","a,#0xfe");
7152 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7156 pic16_emitcode("rrc","a");
7158 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7159 pic16_emitcode("cpl","c");
7160 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7165 pic16_outBitC(result);
7167 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7168 genIfxJump(ifx, "c");
7172 if(pic16_sameRegs(AOP(result),AOP(left))){
7173 /* if left is same as result */
7174 for(;size--; offset++) {
7175 if(AOP_TYPE(right) == AOP_LIT){
7176 int t = (lit >> (offset*8)) & 0x0FFL;
7180 if (IS_AOP_PREG(left)) {
7181 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7182 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7183 pic16_aopPut(AOP(result),"a",offset);
7185 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7186 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7187 pic16_emitcode("xrl","%s,%s",
7188 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7189 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7192 if (AOP_TYPE(left) == AOP_ACC)
7193 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7195 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7196 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7198 if (IS_AOP_PREG(left)) {
7199 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7200 pic16_aopPut(AOP(result),"a",offset);
7202 pic16_emitcode("xrl","%s,a",
7203 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7209 // left & result in different registers
7210 if(AOP_TYPE(result) == AOP_CRY){
7212 // if(size), result in bit
7213 // if(!size && ifx), conditional oper: if(left ^ right)
7214 symbol *tlbl = newiTempLabel(NULL);
7215 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7217 pic16_emitcode("setb","c");
7219 if((AOP_TYPE(right) == AOP_LIT) &&
7220 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7221 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7223 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7224 pic16_emitcode("xrl","a,%s",
7225 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7227 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7232 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7233 pic16_outBitC(result);
7235 jmpTrueOrFalse(ifx, tlbl);
7236 } else for(;(size--);offset++){
7238 // result = left & right
7239 if(AOP_TYPE(right) == AOP_LIT){
7240 int t = (lit >> (offset*8)) & 0x0FFL;
7243 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7244 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7245 pic16_emitcode("movf","%s,w",
7246 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7247 pic16_emitcode("movwf","%s",
7248 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7251 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7252 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7253 pic16_emitcode("comf","%s,w",
7254 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7255 pic16_emitcode("movwf","%s",
7256 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7259 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7260 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7261 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7262 pic16_emitcode("movlw","0x%x",t);
7263 pic16_emitcode("xorwf","%s,w",
7264 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7265 pic16_emitcode("movwf","%s",
7266 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7272 // faster than result <- left, anl result,right
7273 // and better if result is SFR
7274 if (AOP_TYPE(left) == AOP_ACC) {
7275 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7276 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7278 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7279 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7280 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7281 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7283 if ( AOP_TYPE(result) != AOP_ACC){
7284 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7285 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7291 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7292 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7293 pic16_freeAsmop(result,NULL,ic,TRUE);
7296 /*-----------------------------------------------------------------*/
7297 /* genInline - write the inline code out */
7298 /*-----------------------------------------------------------------*/
7299 static void genInline (iCode *ic)
7301 char *buffer, *bp, *bp1;
7303 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7305 _G.inLine += (!options.asmpeep);
7307 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7308 strcpy(buffer,IC_INLINE(ic));
7310 // fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7312 /* emit each line as a code */
7318 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7326 /* print label, use this special format with NULL directive
7327 * to denote that the argument should not be indented with tab */
7328 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7335 if ((bp1 != bp) && *bp1)
7336 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7341 _G.inLine -= (!options.asmpeep);
7344 /*-----------------------------------------------------------------*/
7345 /* genRRC - rotate right with carry */
7346 /*-----------------------------------------------------------------*/
7347 static void genRRC (iCode *ic)
7349 operand *left , *result ;
7350 int size, offset = 0, same;
7352 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7354 /* rotate right with carry */
7356 result=IC_RESULT(ic);
7357 pic16_aopOp (left,ic,FALSE);
7358 pic16_aopOp (result,ic,FALSE);
7360 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7362 same = pic16_sameRegs(AOP(result),AOP(left));
7364 size = AOP_SIZE(result);
7366 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7368 /* get the lsb and put it into the carry */
7369 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7376 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7378 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7379 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7385 pic16_freeAsmop(left,NULL,ic,TRUE);
7386 pic16_freeAsmop(result,NULL,ic,TRUE);
7389 /*-----------------------------------------------------------------*/
7390 /* genRLC - generate code for rotate left with carry */
7391 /*-----------------------------------------------------------------*/
7392 static void genRLC (iCode *ic)
7394 operand *left , *result ;
7395 int size, offset = 0;
7398 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7399 /* rotate right with carry */
7401 result=IC_RESULT(ic);
7402 pic16_aopOp (left,ic,FALSE);
7403 pic16_aopOp (result,ic,FALSE);
7405 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7407 same = pic16_sameRegs(AOP(result),AOP(left));
7409 /* move it to the result */
7410 size = AOP_SIZE(result);
7412 /* get the msb and put it into the carry */
7413 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7420 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7422 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7423 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7430 pic16_freeAsmop(left,NULL,ic,TRUE);
7431 pic16_freeAsmop(result,NULL,ic,TRUE);
7435 /* gpasm can get the highest order bit with HIGH/UPPER
7436 * so the following probably is not needed -- VR */
7438 /*-----------------------------------------------------------------*/
7439 /* genGetHbit - generates code get highest order bit */
7440 /*-----------------------------------------------------------------*/
7441 static void genGetHbit (iCode *ic)
7443 operand *left, *result;
7445 result=IC_RESULT(ic);
7446 pic16_aopOp (left,ic,FALSE);
7447 pic16_aopOp (result,ic,FALSE);
7449 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7450 /* get the highest order byte into a */
7451 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7452 if(AOP_TYPE(result) == AOP_CRY){
7453 pic16_emitcode("rlc","a");
7454 pic16_outBitC(result);
7457 pic16_emitcode("rl","a");
7458 pic16_emitcode("anl","a,#0x01");
7459 pic16_outAcc(result);
7463 pic16_freeAsmop(left,NULL,ic,TRUE);
7464 pic16_freeAsmop(result,NULL,ic,TRUE);
7468 /*-----------------------------------------------------------------*/
7469 /* AccRol - rotate left accumulator by known count */
7470 /*-----------------------------------------------------------------*/
7471 static void AccRol (int shCount)
7473 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7474 shCount &= 0x0007; // shCount : 0..7
7479 pic16_emitcode("rl","a");
7482 pic16_emitcode("rl","a");
7483 pic16_emitcode("rl","a");
7486 pic16_emitcode("swap","a");
7487 pic16_emitcode("rr","a");
7490 pic16_emitcode("swap","a");
7493 pic16_emitcode("swap","a");
7494 pic16_emitcode("rl","a");
7497 pic16_emitcode("rr","a");
7498 pic16_emitcode("rr","a");
7501 pic16_emitcode("rr","a");
7507 /*-----------------------------------------------------------------*/
7508 /* AccLsh - left shift accumulator by known count */
7509 /*-----------------------------------------------------------------*/
7510 static void AccLsh (int shCount)
7512 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7518 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7521 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7522 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7525 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7526 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7529 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7532 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7533 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7536 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7537 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7540 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7544 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7547 /*-----------------------------------------------------------------*/
7548 /* AccRsh - right shift accumulator by known count */
7549 /*-----------------------------------------------------------------*/
7550 static void AccRsh (int shCount, int andmask)
7552 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7557 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7558 // andmask = 0; /* no need */
7561 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7562 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7563 // andmask = 0; /* no need */
7566 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7567 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7570 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7573 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7574 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7577 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7578 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7581 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7586 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7588 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7592 /*-----------------------------------------------------------------*/
7593 /* AccSRsh - signed right shift accumulator by known count */
7594 /*-----------------------------------------------------------------*/
7595 static void AccSRsh (int shCount)
7598 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7601 pic16_emitcode("mov","c,acc.7");
7602 pic16_emitcode("rrc","a");
7603 } else if(shCount == 2){
7604 pic16_emitcode("mov","c,acc.7");
7605 pic16_emitcode("rrc","a");
7606 pic16_emitcode("mov","c,acc.7");
7607 pic16_emitcode("rrc","a");
7609 tlbl = newiTempLabel(NULL);
7610 /* rotate right accumulator */
7611 AccRol(8 - shCount);
7612 /* and kill the higher order bits */
7613 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7614 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7615 pic16_emitcode("orl","a,#0x%02x",
7616 (unsigned char)~SRMask[shCount]);
7617 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7622 /*-----------------------------------------------------------------*/
7623 /* shiftR1Left2Result - shift right one byte from left to result */
7624 /*-----------------------------------------------------------------*/
7625 static void shiftR1Left2ResultSigned (operand *left, int offl,
7626 operand *result, int offr,
7631 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7633 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7637 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7639 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7641 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7642 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7648 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7650 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7652 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7653 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7655 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7656 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7662 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7664 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7665 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7668 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7669 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7670 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7672 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7673 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7675 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7679 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7680 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7681 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7682 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
7683 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7687 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7689 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7690 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7692 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7693 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
7694 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7695 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
7696 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7701 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7702 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7703 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7704 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7705 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7706 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7708 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7709 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7710 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7711 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7712 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7718 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7719 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7720 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7721 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7723 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7724 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7725 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
7733 /*-----------------------------------------------------------------*/
7734 /* shiftR1Left2Result - shift right one byte from left to result */
7735 /*-----------------------------------------------------------------*/
7736 static void shiftR1Left2Result (operand *left, int offl,
7737 operand *result, int offr,
7738 int shCount, int sign)
7742 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7744 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7746 /* Copy the msb into the carry if signed. */
7748 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7758 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7760 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7761 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7767 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7769 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7770 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7773 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7778 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7780 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7781 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7784 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7785 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7786 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7787 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7791 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7792 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7793 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7797 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7798 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7799 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7801 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7806 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7807 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7808 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7809 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7810 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7815 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7816 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7817 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7826 /*-----------------------------------------------------------------*/
7827 /* shiftL1Left2Result - shift left one byte from left to result */
7828 /*-----------------------------------------------------------------*/
7829 static void shiftL1Left2Result (operand *left, int offl,
7830 operand *result, int offr, int shCount)
7835 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7837 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7838 DEBUGpic16_emitcode ("; ***","same = %d",same);
7839 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7841 /* shift left accumulator */
7842 //AccLsh(shCount); // don't comment out just yet...
7843 // pic16_aopPut(AOP(result),"a",offr);
7847 /* Shift left 1 bit position */
7848 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7850 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7852 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7853 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7857 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7858 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7859 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7860 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7863 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7864 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7865 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7866 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7867 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7870 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7871 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7872 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7875 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7876 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7877 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7878 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7881 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7882 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7883 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7884 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7885 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7888 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7889 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7890 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7894 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7899 /*-----------------------------------------------------------------*/
7900 /* movLeft2Result - move byte from left to result */
7901 /*-----------------------------------------------------------------*/
7902 static void movLeft2Result (operand *left, int offl,
7903 operand *result, int offr)
7906 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7907 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7908 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7910 if (*l == '@' && (IS_AOP_PREG(result))) {
7911 pic16_emitcode("mov","a,%s",l);
7912 pic16_aopPut(AOP(result),"a",offr);
7914 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7915 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7920 /*-----------------------------------------------------------------*/
7921 /* shiftL2Left2Result - shift left two bytes from left to result */
7922 /*-----------------------------------------------------------------*/
7923 static void shiftL2Left2Result (operand *left, int offl,
7924 operand *result, int offr, int shCount)
7926 int same = pic16_sameRegs(AOP(result), AOP(left));
7929 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7931 if (same && (offl != offr)) { // shift bytes
7934 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7935 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7937 } else { // just treat as different later on
7950 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7951 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7952 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7956 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7957 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7963 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7964 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7965 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7966 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7967 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7968 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7969 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7971 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7972 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7976 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7977 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7978 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7979 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7980 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7981 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7982 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7983 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7984 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7985 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7988 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7989 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7990 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7991 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7992 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8002 /* note, use a mov/add for the shift since the mov has a
8003 chance of getting optimized out */
8004 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8005 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8006 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8007 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8012 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8013 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8019 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8020 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8021 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8022 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8023 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8024 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8025 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8026 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8030 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8031 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8035 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8036 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8037 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8038 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8040 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8041 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8042 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8043 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8044 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8045 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8046 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8047 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8050 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8051 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8052 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8053 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8054 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8059 /*-----------------------------------------------------------------*/
8060 /* shiftR2Left2Result - shift right two bytes from left to result */
8061 /*-----------------------------------------------------------------*/
8062 static void shiftR2Left2Result (operand *left, int offl,
8063 operand *result, int offr,
8064 int shCount, int sign)
8066 int same = pic16_sameRegs(AOP(result), AOP(left));
8068 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8070 if (same && (offl != offr)) { // shift right bytes
8073 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8074 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8076 } else { // just treat as different later on
8088 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8093 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8094 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8096 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8097 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8098 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8099 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8104 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8107 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8108 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8115 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
8116 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
8117 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8119 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8120 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
8121 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8122 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8124 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8125 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8126 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8128 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8129 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8130 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8131 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8132 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8136 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8137 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8141 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
8142 pic16_emitpcode(POC_BTFSC,
8143 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
8144 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8152 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8153 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8155 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8156 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8157 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8158 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8160 pic16_emitpcode(POC_BTFSC,
8161 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8162 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8164 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8165 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8166 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8167 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8169 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8170 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8171 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8172 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8173 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8174 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8175 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8176 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8178 pic16_emitpcode(POC_BTFSC,
8179 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8180 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8182 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8183 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8190 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8191 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8192 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8193 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8196 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8198 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8203 /*-----------------------------------------------------------------*/
8204 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8205 /*-----------------------------------------------------------------*/
8206 static void shiftLLeftOrResult (operand *left, int offl,
8207 operand *result, int offr, int shCount)
8209 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8211 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8212 /* shift left accumulator */
8214 /* or with result */
8215 /* back to result */
8216 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8219 /*-----------------------------------------------------------------*/
8220 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8221 /*-----------------------------------------------------------------*/
8222 static void shiftRLeftOrResult (operand *left, int offl,
8223 operand *result, int offr, int shCount)
8225 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8227 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8228 /* shift right accumulator */
8230 /* or with result */
8231 /* back to result */
8232 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8235 /*-----------------------------------------------------------------*/
8236 /* genlshOne - left shift a one byte quantity by known count */
8237 /*-----------------------------------------------------------------*/
8238 static void genlshOne (operand *result, operand *left, int shCount)
8240 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8241 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8244 /*-----------------------------------------------------------------*/
8245 /* genlshTwo - left shift two bytes by known amount != 0 */
8246 /*-----------------------------------------------------------------*/
8247 static void genlshTwo (operand *result,operand *left, int shCount)
8251 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8252 size = pic16_getDataSize(result);
8254 /* if shCount >= 8 */
8260 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8262 movLeft2Result(left, LSB, result, MSB16);
8264 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8267 /* 1 <= shCount <= 7 */
8270 shiftL1Left2Result(left, LSB, result, LSB, shCount);
8272 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8276 /*-----------------------------------------------------------------*/
8277 /* shiftLLong - shift left one long from left to result */
8278 /* offr = LSB or MSB16 */
8279 /*-----------------------------------------------------------------*/
8280 static void shiftLLong (operand *left, operand *result, int offr )
8282 int size = AOP_SIZE(result);
8283 int same = pic16_sameRegs(AOP(left),AOP(result));
8286 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8288 if (same && (offr == MSB16)) { //shift one byte
8289 for(i=size-1;i>=MSB16;i--) {
8290 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8291 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8294 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8297 if (size >= LSB+offr ){
8299 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8301 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8302 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8306 if(size >= MSB16+offr){
8308 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8310 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8311 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8315 if(size >= MSB24+offr){
8317 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8319 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8320 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8324 if(size > MSB32+offr){
8326 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8328 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8329 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8333 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8337 /*-----------------------------------------------------------------*/
8338 /* genlshFour - shift four byte by a known amount != 0 */
8339 /*-----------------------------------------------------------------*/
8340 static void genlshFour (operand *result, operand *left, int shCount)
8344 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8345 size = AOP_SIZE(result);
8347 /* if shifting more that 3 bytes */
8348 if (shCount >= 24 ) {
8351 /* lowest order of left goes to the highest
8352 order of the destination */
8353 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8355 movLeft2Result(left, LSB, result, MSB32);
8357 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8358 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8359 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8364 /* more than two bytes */
8365 else if ( shCount >= 16 ) {
8366 /* lower order two bytes goes to higher order two bytes */
8368 /* if some more remaining */
8370 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8372 movLeft2Result(left, MSB16, result, MSB32);
8373 movLeft2Result(left, LSB, result, MSB24);
8375 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8376 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8380 /* if more than 1 byte */
8381 else if ( shCount >= 8 ) {
8382 /* lower order three bytes goes to higher order three bytes */
8386 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8388 movLeft2Result(left, LSB, result, MSB16);
8390 else{ /* size = 4 */
8392 movLeft2Result(left, MSB24, result, MSB32);
8393 movLeft2Result(left, MSB16, result, MSB24);
8394 movLeft2Result(left, LSB, result, MSB16);
8395 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8397 else if(shCount == 1)
8398 shiftLLong(left, result, MSB16);
8400 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8401 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8402 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8403 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8408 /* 1 <= shCount <= 7 */
8409 else if(shCount <= 3)
8411 shiftLLong(left, result, LSB);
8412 while(--shCount >= 1)
8413 shiftLLong(result, result, LSB);
8415 /* 3 <= shCount <= 7, optimize */
8417 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8418 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8419 shiftL2Left2Result(left, LSB, result, LSB, shCount);
8423 /*-----------------------------------------------------------------*/
8424 /* genLeftShiftLiteral - left shifting by known count */
8425 /*-----------------------------------------------------------------*/
8426 static void genLeftShiftLiteral (operand *left,
8431 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8434 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8435 pic16_freeAsmop(right,NULL,ic,TRUE);
8437 pic16_aopOp(left,ic,FALSE);
8438 pic16_aopOp(result,ic,FALSE);
8440 size = getSize(operandType(result));
8443 pic16_emitcode("; shift left ","result %d, left %d",size,
8447 /* I suppose that the left size >= result size */
8450 movLeft2Result(left, size, result, size);
8454 else if(shCount >= (size * 8))
8456 pic16_aopPut(AOP(result),zero,size);
8460 genlshOne (result,left,shCount);
8465 genlshTwo (result,left,shCount);
8469 genlshFour (result,left,shCount);
8473 pic16_freeAsmop(left,NULL,ic,TRUE);
8474 pic16_freeAsmop(result,NULL,ic,TRUE);
8477 /*-----------------------------------------------------------------*
8478 * genMultiAsm - repeat assembly instruction for size of register.
8479 * if endian == 1, then the high byte (i.e base address + size of
8480 * register) is used first else the low byte is used first;
8481 *-----------------------------------------------------------------*/
8482 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8487 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8500 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
8505 /*-----------------------------------------------------------------*/
8506 /* genLeftShift - generates code for left shifting */
8507 /*-----------------------------------------------------------------*/
8508 static void genLeftShift (iCode *ic)
8510 operand *left,*right, *result;
8513 symbol *tlbl , *tlbl1;
8516 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8518 right = IC_RIGHT(ic);
8520 result = IC_RESULT(ic);
8522 pic16_aopOp(right,ic,FALSE);
8524 /* if the shift count is known then do it
8525 as efficiently as possible */
8526 if (AOP_TYPE(right) == AOP_LIT) {
8527 genLeftShiftLiteral (left,right,result,ic);
8531 /* shift count is unknown then we have to form
8532 a loop get the loop count in B : Note: we take
8533 only the lower order byte since shifting
8534 more that 32 bits make no sense anyway, ( the
8535 largest size of an object can be only 32 bits ) */
8538 pic16_aopOp(left,ic,FALSE);
8539 pic16_aopOp(result,ic,FALSE);
8541 /* now move the left to the result if they are not the
8543 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8544 AOP_SIZE(result) > 1) {
8546 size = AOP_SIZE(result);
8549 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8550 if (*l == '@' && (IS_AOP_PREG(result))) {
8552 pic16_emitcode("mov","a,%s",l);
8553 pic16_aopPut(AOP(result),"a",offset);
8555 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8556 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8557 //pic16_aopPut(AOP(result),l,offset);
8563 size = AOP_SIZE(result);
8565 /* if it is only one byte then */
8567 if(optimized_for_speed) {
8568 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8569 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8570 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8571 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8572 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8573 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8574 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8575 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
8576 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
8577 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
8578 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8579 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
8582 tlbl = newiTempLabel(NULL);
8583 if (!pic16_sameRegs(AOP(left),AOP(result))) {
8584 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8585 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8588 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8589 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
8590 pic16_emitpLabel(tlbl->key);
8591 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8592 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8594 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8599 if (pic16_sameRegs(AOP(left),AOP(result))) {
8601 tlbl = newiTempLabel(NULL);
8602 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
8603 genMultiAsm(POC_RRCF, result, size,1);
8604 pic16_emitpLabel(tlbl->key);
8605 genMultiAsm(POC_RLCF, result, size,0);
8606 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
8608 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8612 //tlbl = newiTempLabel(NULL);
8614 //tlbl1 = newiTempLabel(NULL);
8616 //reAdjustPreg(AOP(result));
8618 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8619 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8620 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8622 //pic16_emitcode("add","a,acc");
8623 //pic16_aopPut(AOP(result),"a",offset++);
8625 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8627 // pic16_emitcode("rlc","a");
8628 // pic16_aopPut(AOP(result),"a",offset++);
8630 //reAdjustPreg(AOP(result));
8632 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8633 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8636 tlbl = newiTempLabel(NULL);
8637 tlbl1= newiTempLabel(NULL);
8639 size = AOP_SIZE(result);
8642 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8644 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8646 /* offset should be 0, 1 or 3 */
8648 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8650 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8652 pic16_emitpcode(POC_MOVWF, pctemp);
8655 pic16_emitpLabel(tlbl->key);
8658 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
8660 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
8662 pic16_emitpcode(POC_DECFSZ, pctemp);
8663 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8664 pic16_emitpLabel(tlbl1->key);
8666 pic16_popReleaseTempReg(pctemp);
8670 pic16_freeAsmop (right,NULL,ic,TRUE);
8671 pic16_freeAsmop(left,NULL,ic,TRUE);
8672 pic16_freeAsmop(result,NULL,ic,TRUE);
8675 /*-----------------------------------------------------------------*/
8676 /* genrshOne - right shift a one byte quantity by known count */
8677 /*-----------------------------------------------------------------*/
8678 static void genrshOne (operand *result, operand *left,
8679 int shCount, int sign)
8681 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8682 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8685 /*-----------------------------------------------------------------*/
8686 /* genrshTwo - right shift two bytes by known amount != 0 */
8687 /*-----------------------------------------------------------------*/
8688 static void genrshTwo (operand *result,operand *left,
8689 int shCount, int sign)
8691 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8692 /* if shCount >= 8 */
8696 shiftR1Left2Result(left, MSB16, result, LSB,
8699 movLeft2Result(left, MSB16, result, LSB);
8701 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8704 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8705 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8709 /* 1 <= shCount <= 7 */
8711 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
8714 /*-----------------------------------------------------------------*/
8715 /* shiftRLong - shift right one long from left to result */
8716 /* offl = LSB or MSB16 */
8717 /*-----------------------------------------------------------------*/
8718 static void shiftRLong (operand *left, int offl,
8719 operand *result, int sign)
8721 int size = AOP_SIZE(result);
8722 int same = pic16_sameRegs(AOP(left),AOP(result));
8724 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8726 if (same && (offl == MSB16)) { //shift one byte right
8727 for(i=MSB16;i<size;i++) {
8728 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8729 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8734 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8740 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8742 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8743 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8747 /* add sign of "a" */
8748 pic16_addSign(result, MSB32, sign);
8752 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8754 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8755 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8759 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8761 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8762 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8766 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8769 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8770 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8775 /*-----------------------------------------------------------------*/
8776 /* genrshFour - shift four byte by a known amount != 0 */
8777 /*-----------------------------------------------------------------*/
8778 static void genrshFour (operand *result, operand *left,
8779 int shCount, int sign)
8781 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8782 /* if shifting more that 3 bytes */
8783 if(shCount >= 24 ) {
8786 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8788 movLeft2Result(left, MSB32, result, LSB);
8790 pic16_addSign(result, MSB16, sign);
8792 else if(shCount >= 16){
8795 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8797 movLeft2Result(left, MSB24, result, LSB);
8798 movLeft2Result(left, MSB32, result, MSB16);
8800 pic16_addSign(result, MSB24, sign);
8802 else if(shCount >= 8){
8805 shiftRLong(left, MSB16, result, sign);
8806 else if(shCount == 0){
8807 movLeft2Result(left, MSB16, result, LSB);
8808 movLeft2Result(left, MSB24, result, MSB16);
8809 movLeft2Result(left, MSB32, result, MSB24);
8810 pic16_addSign(result, MSB32, sign);
8812 else{ //shcount >= 2
8813 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8814 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8815 /* the last shift is signed */
8816 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8817 pic16_addSign(result, MSB32, sign);
8820 else{ /* 1 <= shCount <= 7 */
8822 shiftRLong(left, LSB, result, sign);
8824 shiftRLong(result, LSB, result, sign);
8827 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8828 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8829 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8834 /*-----------------------------------------------------------------*/
8835 /* genRightShiftLiteral - right shifting by known count */
8836 /*-----------------------------------------------------------------*/
8837 static void genRightShiftLiteral (operand *left,
8843 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8846 pic16_freeAsmop(right,NULL,ic,TRUE);
8848 pic16_aopOp(left,ic,FALSE);
8849 pic16_aopOp(result,ic,FALSE);
8851 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8854 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8858 lsize = pic16_getDataSize(left);
8859 res_size = pic16_getDataSize(result);
8860 /* test the LEFT size !!! */
8862 /* I suppose that the left size >= result size */
8865 movLeft2Result(left, lsize, result, res_size);
8868 else if(shCount >= (lsize * 8)){
8871 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8873 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8874 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8879 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8880 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8881 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8883 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8888 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8895 genrshOne (result,left,shCount,sign);
8899 genrshTwo (result,left,shCount,sign);
8903 genrshFour (result,left,shCount,sign);
8911 pic16_freeAsmop(left,NULL,ic,TRUE);
8912 pic16_freeAsmop(result,NULL,ic,TRUE);
8915 /*-----------------------------------------------------------------*/
8916 /* genSignedRightShift - right shift of signed number */
8917 /*-----------------------------------------------------------------*/
8918 static void genSignedRightShift (iCode *ic)
8920 operand *right, *left, *result;
8923 symbol *tlbl, *tlbl1 ;
8926 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8928 /* we do it the hard way put the shift count in b
8929 and loop thru preserving the sign */
8930 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8932 right = IC_RIGHT(ic);
8934 result = IC_RESULT(ic);
8936 pic16_aopOp(right,ic,FALSE);
8937 pic16_aopOp(left,ic,FALSE);
8938 pic16_aopOp(result,ic,FALSE);
8941 if ( AOP_TYPE(right) == AOP_LIT) {
8942 genRightShiftLiteral (left,right,result,ic,1);
8945 /* shift count is unknown then we have to form
8946 a loop get the loop count in B : Note: we take
8947 only the lower order byte since shifting
8948 more that 32 bits make no sense anyway, ( the
8949 largest size of an object can be only 32 bits ) */
8951 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8952 //pic16_emitcode("inc","b");
8953 //pic16_freeAsmop (right,NULL,ic,TRUE);
8954 //pic16_aopOp(left,ic,FALSE);
8955 //pic16_aopOp(result,ic,FALSE);
8957 /* now move the left to the result if they are not the
8959 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
8960 AOP_SIZE(result) > 1) {
8962 size = AOP_SIZE(result);
8966 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8967 if (*l == '@' && IS_AOP_PREG(result)) {
8969 pic16_emitcode("mov","a,%s",l);
8970 pic16_aopPut(AOP(result),"a",offset);
8972 pic16_aopPut(AOP(result),l,offset);
8974 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
8975 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8981 /* mov the highest order bit to OVR */
8982 tlbl = newiTempLabel(NULL);
8983 tlbl1= newiTempLabel(NULL);
8985 size = AOP_SIZE(result);
8988 pctemp = pic16_popGetTempReg(); /* grab a temporary working register. */
8990 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8992 /* offset should be 0, 1 or 3 */
8993 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8995 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
8997 pic16_emitpcode(POC_MOVWF, pctemp);
9000 pic16_emitpLabel(tlbl->key);
9002 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
9003 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
9006 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
9009 pic16_emitpcode(POC_DECFSZ, pctemp);
9010 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9011 pic16_emitpLabel(tlbl1->key);
9013 pic16_popReleaseTempReg(pctemp);
9015 size = AOP_SIZE(result);
9017 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
9018 pic16_emitcode("rlc","a");
9019 pic16_emitcode("mov","ov,c");
9020 /* if it is only one byte then */
9022 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9024 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9025 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9026 pic16_emitcode("mov","c,ov");
9027 pic16_emitcode("rrc","a");
9028 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9029 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9030 pic16_aopPut(AOP(result),"a",0);
9034 reAdjustPreg(AOP(result));
9035 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9036 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9037 pic16_emitcode("mov","c,ov");
9039 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9041 pic16_emitcode("rrc","a");
9042 pic16_aopPut(AOP(result),"a",offset--);
9044 reAdjustPreg(AOP(result));
9045 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9046 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9051 pic16_freeAsmop(left,NULL,ic,TRUE);
9052 pic16_freeAsmop(result,NULL,ic,TRUE);
9053 pic16_freeAsmop(right,NULL,ic,TRUE);
9056 /*-----------------------------------------------------------------*/
9057 /* genRightShift - generate code for right shifting */
9058 /*-----------------------------------------------------------------*/
9059 static void genRightShift (iCode *ic)
9061 operand *right, *left, *result;
9065 symbol *tlbl, *tlbl1 ;
9067 /* if signed then we do it the hard way preserve the
9068 sign bit moving it inwards */
9069 letype = getSpec(operandType(IC_LEFT(ic)));
9070 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9072 if (!SPEC_USIGN(letype)) {
9073 genSignedRightShift (ic);
9077 /* signed & unsigned types are treated the same : i.e. the
9078 signed is NOT propagated inwards : quoting from the
9079 ANSI - standard : "for E1 >> E2, is equivalent to division
9080 by 2**E2 if unsigned or if it has a non-negative value,
9081 otherwise the result is implementation defined ", MY definition
9082 is that the sign does not get propagated */
9084 right = IC_RIGHT(ic);
9086 result = IC_RESULT(ic);
9088 pic16_aopOp(right,ic,FALSE);
9090 /* if the shift count is known then do it
9091 as efficiently as possible */
9092 if (AOP_TYPE(right) == AOP_LIT) {
9093 genRightShiftLiteral (left,right,result,ic, 0);
9097 /* shift count is unknown then we have to form
9098 a loop get the loop count in B : Note: we take
9099 only the lower order byte since shifting
9100 more that 32 bits make no sense anyway, ( the
9101 largest size of an object can be only 32 bits ) */
9103 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9104 pic16_emitcode("inc","b");
9105 pic16_aopOp(left,ic,FALSE);
9106 pic16_aopOp(result,ic,FALSE);
9108 /* now move the left to the result if they are not the
9110 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9111 AOP_SIZE(result) > 1) {
9113 size = AOP_SIZE(result);
9116 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9117 if (*l == '@' && IS_AOP_PREG(result)) {
9119 pic16_emitcode("mov","a,%s",l);
9120 pic16_aopPut(AOP(result),"a",offset);
9122 pic16_aopPut(AOP(result),l,offset);
9127 tlbl = newiTempLabel(NULL);
9128 tlbl1= newiTempLabel(NULL);
9129 size = AOP_SIZE(result);
9132 /* if it is only one byte then */
9135 tlbl = newiTempLabel(NULL);
9136 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9137 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9138 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9141 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9142 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9143 pic16_emitpLabel(tlbl->key);
9144 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9145 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9147 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9152 reAdjustPreg(AOP(result));
9153 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9154 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9157 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9159 pic16_emitcode("rrc","a");
9160 pic16_aopPut(AOP(result),"a",offset--);
9162 reAdjustPreg(AOP(result));
9164 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9165 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9168 pic16_freeAsmop(left,NULL,ic,TRUE);
9169 pic16_freeAsmop (right,NULL,ic,TRUE);
9170 pic16_freeAsmop(result,NULL,ic,TRUE);
9173 /*-----------------------------------------------------------------*/
9174 /* genUnpackBits - generates code for unpacking bits */
9175 /*-----------------------------------------------------------------*/
9176 static void genUnpackBits (operand *result, char *rname, int ptype)
9183 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9184 etype = getSpec(operandType(result));
9186 /* read the first byte */
9193 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9196 pic16_emitcode("clr","a");
9197 pic16_emitcode("movc","a","@a+dptr");
9202 /* if we have bitdisplacement then it fits */
9203 /* into this byte completely or if length is */
9204 /* less than a byte */
9205 if ((shCnt = SPEC_BSTR(etype)) ||
9206 (SPEC_BLEN(etype) <= 8)) {
9208 /* shift right acc */
9211 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9212 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9214 /* VR -- normally I would use the following, but since we use the hack,
9215 * to avoid the masking from AccRsh, why not mask it right now? */
9218 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9221 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9227 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9228 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9231 /* bit field did not fit in a byte */
9232 rlen = SPEC_BLEN(etype) - 8;
9233 pic16_aopPut(AOP(result),"a",offset++);
9240 pic16_emitcode("inc","%s",rname);
9241 pic16_emitcode("mov","a,@%s",rname);
9245 pic16_emitcode("inc","%s",rname);
9246 pic16_emitcode("movx","a,@%s",rname);
9250 pic16_emitcode("inc","dptr");
9251 pic16_emitcode("movx","a,@dptr");
9255 pic16_emitcode("clr","a");
9256 pic16_emitcode("inc","dptr");
9257 pic16_emitcode("movc","a","@a+dptr");
9261 pic16_emitcode("inc","dptr");
9262 pic16_emitcode("lcall","__gptrget");
9267 /* if we are done */
9271 pic16_aopPut(AOP(result),"a",offset++);
9276 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9277 pic16_aopPut(AOP(result),"a",offset);
9284 static void genDataPointerGet(operand *left,
9288 int size, offset = 0, leoffset=0 ;
9290 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9291 pic16_aopOp(result, ic, FALSE);
9293 size = AOP_SIZE(result);
9294 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9298 /* The following tests may save a redudant movff instruction when
9299 * accessing unions */
9301 /* if they are the same */
9302 if (operandsEqu (left, result)) {
9303 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9309 /* if they are the same registers */
9310 if (pic16_sameRegs(AOP(left),AOP(result))) {
9311 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9317 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9318 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9319 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9326 if ( AOP_TYPE(left) == AOP_PCODE) {
9327 fprintf(stderr,"genDataPointerGet %s, %d\n",
9328 AOP(left)->aopu.pcop->name,
9329 (AOP(left)->aopu.pcop->type == PO_DIR)?
9330 PCOR(AOP(left)->aopu.pcop)->instance:
9331 PCOI(AOP(left)->aopu.pcop)->offset);
9335 if(AOP(left)->aopu.pcop->type == PO_DIR)
9336 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9338 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9341 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9343 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9344 || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9345 mov2w(AOP(left), offset); // patch 8
9346 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9348 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9349 pic16_popGet(AOP(left), offset), //patch 8
9350 pic16_popGet(AOP(result), offset)));
9358 pic16_freeAsmop(result,NULL,ic,TRUE);
9361 void pic16_loadFSR0(operand *op)
9363 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9367 /*-----------------------------------------------------------------*/
9368 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
9369 /*-----------------------------------------------------------------*/
9370 static void genNearPointerGet (operand *left,
9375 //regs *preg = NULL ;
9376 sym_link *rtype, *retype;
9377 sym_link *ltype = operandType(left);
9379 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9380 rtype = operandType(result);
9381 retype= getSpec(rtype);
9383 pic16_aopOp(left,ic,FALSE);
9385 // pic16_DumpOp("(left)",left);
9386 // pic16_DumpOp("(result)",result);
9388 /* if left is rematerialisable and
9389 * result is not bit variable type and
9390 * the left is pointer to data space i.e
9391 * lower 128 bytes of space */
9392 if (AOP_TYPE(left) == AOP_PCODE
9393 && !IS_BITFIELD(retype)
9394 && DCL_TYPE(ltype) == POINTER) {
9396 genDataPointerGet (left,result,ic);
9397 pic16_freeAsmop(left, NULL, ic, TRUE);
9401 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9403 /* if the value is already in a pointer register
9404 * then don't need anything more */
9405 if (!AOP_INPREG(AOP(left))) {
9406 /* otherwise get a free pointer register */
9407 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9409 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9410 if( (AOP_TYPE(left) == AOP_PCODE)
9411 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9412 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9414 pic16_loadFSR0( left ); // patch 10
9416 // set up FSR0 with address from left
9417 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9418 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9422 // rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9424 pic16_aopOp (result,ic,FALSE);
9426 /* if bitfield then unpack the bits */
9427 if (IS_BITFIELD(retype))
9428 genUnpackBits (result, NULL, POINTER);
9430 /* we have can just get the values */
9431 int size = AOP_SIZE(result);
9434 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9437 /* fsr0 is loaded already -- VR */
9438 // pic16_loadFSR0( left );
9440 // pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9441 // pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9445 pic16_emitpcode(POC_MOVFF,
9446 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9447 pic16_popGet(AOP(result), offset++)));
9449 pic16_emitpcode(POC_MOVFF,
9450 pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9451 pic16_popGet(AOP(result), offset++)));
9455 // pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9456 // pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9458 pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9462 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9464 pic16_emitcode("mov","a,@%s",rname);
9465 pic16_aopPut(AOP(result),"a",offset);
9467 sprintf(buffer,"@%s",rname);
9468 pic16_aopPut(AOP(result),buffer,offset);
9472 pic16_emitcode("inc","%s",rname);
9477 /* now some housekeeping stuff */
9479 /* we had to allocate for this iCode */
9480 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9481 pic16_freeAsmop(NULL,aop,ic,TRUE);
9483 /* we did not allocate which means left
9484 already in a pointer register, then
9485 if size > 0 && this could be used again
9486 we have to point it back to where it
9488 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9489 if (AOP_SIZE(result) > 1 &&
9490 !OP_SYMBOL(left)->remat &&
9491 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9493 // int size = AOP_SIZE(result) - 1;
9495 // pic16_emitcode("dec","%s",rname);
9500 pic16_freeAsmop(left,NULL,ic,TRUE);
9501 pic16_freeAsmop(result,NULL,ic,TRUE);
9505 /*-----------------------------------------------------------------*/
9506 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
9507 /*-----------------------------------------------------------------*/
9508 static void genPagedPointerGet (operand *left,
9515 sym_link *rtype, *retype;
9517 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9519 rtype = operandType(result);
9520 retype= getSpec(rtype);
9522 pic16_aopOp(left,ic,FALSE);
9524 /* if the value is already in a pointer register
9525 then don't need anything more */
9526 if (!AOP_INPREG(AOP(left))) {
9527 /* otherwise get a free pointer register */
9529 preg = getFreePtr(ic,&aop,FALSE);
9530 pic16_emitcode("mov","%s,%s",
9532 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9533 rname = preg->name ;
9535 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9537 pic16_freeAsmop(left,NULL,ic,TRUE);
9538 pic16_aopOp (result,ic,FALSE);
9540 /* if bitfield then unpack the bits */
9541 if (IS_BITFIELD(retype))
9542 genUnpackBits (result,rname,PPOINTER);
9544 /* we have can just get the values */
9545 int size = AOP_SIZE(result);
9550 pic16_emitcode("movx","a,@%s",rname);
9551 pic16_aopPut(AOP(result),"a",offset);
9556 pic16_emitcode("inc","%s",rname);
9560 /* now some housekeeping stuff */
9562 /* we had to allocate for this iCode */
9563 pic16_freeAsmop(NULL,aop,ic,TRUE);
9565 /* we did not allocate which means left
9566 already in a pointer register, then
9567 if size > 0 && this could be used again
9568 we have to point it back to where it
9570 if (AOP_SIZE(result) > 1 &&
9571 !OP_SYMBOL(left)->remat &&
9572 ( OP_SYMBOL(left)->liveTo > ic->seq ||
9574 int size = AOP_SIZE(result) - 1;
9576 pic16_emitcode("dec","%s",rname);
9581 pic16_freeAsmop(result,NULL,ic,TRUE);
9586 /*-----------------------------------------------------------------*/
9587 /* genFarPointerGet - gget value from far space */
9588 /*-----------------------------------------------------------------*/
9589 static void genFarPointerGet (operand *left,
9590 operand *result, iCode *ic)
9593 sym_link *retype = getSpec(operandType(result));
9595 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9597 pic16_aopOp(left,ic,FALSE);
9599 /* if the operand is already in dptr
9600 then we do nothing else we move the value to dptr */
9601 if (AOP_TYPE(left) != AOP_STR) {
9602 /* if this is remateriazable */
9603 if (AOP_TYPE(left) == AOP_IMMD)
9604 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9605 else { /* we need to get it byte by byte */
9606 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9607 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9608 if (options.model == MODEL_FLAT24)
9610 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9614 /* so dptr know contains the address */
9615 pic16_freeAsmop(left,NULL,ic,TRUE);
9616 pic16_aopOp(result,ic,FALSE);
9618 /* if bit then unpack */
9619 if (IS_BITFIELD(retype))
9620 genUnpackBits(result,"dptr",FPOINTER);
9622 size = AOP_SIZE(result);
9626 pic16_emitcode("movx","a,@dptr");
9627 pic16_aopPut(AOP(result),"a",offset++);
9629 pic16_emitcode("inc","dptr");
9633 pic16_freeAsmop(result,NULL,ic,TRUE);
9636 /*-----------------------------------------------------------------*/
9637 /* genCodePointerGet - get value from code space */
9638 /*-----------------------------------------------------------------*/
9639 static void genCodePointerGet (operand *left,
9640 operand *result, iCode *ic)
9643 sym_link *retype = getSpec(operandType(result));
9645 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9647 pic16_aopOp(left,ic,FALSE);
9649 /* if the operand is already in dptr
9650 then we do nothing else we move the value to dptr */
9651 if (AOP_TYPE(left) != AOP_STR) {
9652 /* if this is remateriazable */
9653 if (AOP_TYPE(left) == AOP_IMMD)
9654 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9655 else { /* we need to get it byte by byte */
9656 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9657 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9658 if (options.model == MODEL_FLAT24)
9660 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9664 /* so dptr know contains the address */
9665 pic16_freeAsmop(left,NULL,ic,TRUE);
9666 pic16_aopOp(result,ic,FALSE);
9668 /* if bit then unpack */
9669 if (IS_BITFIELD(retype))
9670 genUnpackBits(result,"dptr",CPOINTER);
9672 size = AOP_SIZE(result);
9676 pic16_emitcode("clr","a");
9677 pic16_emitcode("movc","a,@a+dptr");
9678 pic16_aopPut(AOP(result),"a",offset++);
9680 pic16_emitcode("inc","dptr");
9684 pic16_freeAsmop(result,NULL,ic,TRUE);
9687 /*-----------------------------------------------------------------*/
9688 /* genGenPointerGet - gget value from generic pointer space */
9689 /*-----------------------------------------------------------------*/
9690 static void genGenPointerGet (operand *left,
9691 operand *result, iCode *ic)
9693 int size, offset, lit;
9694 sym_link *retype = getSpec(operandType(result));
9696 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9697 pic16_aopOp(left,ic,FALSE);
9698 pic16_aopOp(result,ic,FALSE);
9699 size = AOP_SIZE(result);
9701 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9703 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9705 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9706 // load FSR0 from immediate
9707 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9709 // pic16_loadFSR0( left );
9714 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9716 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9723 else { /* we need to get it byte by byte */
9724 // set up FSR0 with address from left
9725 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9726 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9732 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9734 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9741 /* if bit then unpack */
9742 if (IS_BITFIELD(retype))
9743 genUnpackBits(result,"BAD",GPOINTER);
9746 pic16_freeAsmop(left,NULL,ic,TRUE);
9747 pic16_freeAsmop(result,NULL,ic,TRUE);
9751 /*-----------------------------------------------------------------*/
9752 /* genConstPointerGet - get value from const generic pointer space */
9753 /*-----------------------------------------------------------------*/
9754 static void genConstPointerGet (operand *left,
9755 operand *result, iCode *ic)
9757 //sym_link *retype = getSpec(operandType(result));
9758 // symbol *albl = newiTempLabel(NULL); // patch 15
9759 // symbol *blbl = newiTempLabel(NULL); //
9760 // PIC_OPCODE poc; // patch 15
9764 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9765 pic16_aopOp(left,ic,FALSE);
9766 pic16_aopOp(result,ic,TRUE);
9767 size = AOP_SIZE(result);
9769 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9771 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9773 pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9774 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9775 pic16_emitpLabel(albl->key);
9777 poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9779 /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9780 pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9781 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9782 pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9783 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9785 pic16_emitpLabel(blbl->key);
9787 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9791 // set up table pointer
9792 if( (AOP_TYPE(left) == AOP_PCODE)
9793 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9794 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ......
9796 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9797 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9798 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9799 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9800 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9801 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9805 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9806 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9807 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9813 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9814 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9818 pic16_freeAsmop(left,NULL,ic,TRUE);
9819 pic16_freeAsmop(result,NULL,ic,TRUE);
9824 /*-----------------------------------------------------------------*/
9825 /* genPointerGet - generate code for pointer get */
9826 /*-----------------------------------------------------------------*/
9827 static void genPointerGet (iCode *ic)
9829 operand *left, *result ;
9830 sym_link *type, *etype;
9833 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9836 result = IC_RESULT(ic) ;
9838 /* depending on the type of pointer we need to
9839 move it to the correct pointer register */
9840 type = operandType(left);
9841 etype = getSpec(type);
9844 if (IS_PTR_CONST(type))
9846 if (IS_CODEPTR(type))
9848 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9850 /* if left is of type of pointer then it is simple */
9851 if (IS_PTR(type) && !IS_FUNC(type->next))
9852 p_type = DCL_TYPE(type);
9854 /* we have to go by the storage class */
9855 p_type = PTR_TYPE(SPEC_OCLS(etype));
9857 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9859 if (SPEC_OCLS(etype)->codesp ) {
9860 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9861 //p_type = CPOINTER ;
9864 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9865 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9866 /*p_type = FPOINTER ;*/
9868 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9869 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9870 /* p_type = PPOINTER; */
9872 if (SPEC_OCLS(etype) == idata )
9873 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9874 /* p_type = IPOINTER; */
9876 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9877 /* p_type = POINTER ; */
9880 /* now that we have the pointer type we assign
9881 the pointer values */
9886 genNearPointerGet (left,result,ic);
9890 genPagedPointerGet(left,result,ic);
9894 genFarPointerGet (left,result,ic);
9898 genConstPointerGet (left,result,ic);
9899 //pic16_emitcodePointerGet (left,result,ic);
9904 if (IS_PTR_CONST(type))
9905 genConstPointerGet (left,result,ic);
9908 genGenPointerGet (left,result,ic);
9912 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9913 "genPointerGet: illegal pointer type");
9919 /*-----------------------------------------------------------------*/
9920 /* genPackBits - generates code for packed bit storage */
9921 /*-----------------------------------------------------------------*/
9922 static void genPackBits (sym_link *etype ,
9924 char *rname, int p_type)
9932 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9933 blen = SPEC_BLEN(etype);
9934 bstr = SPEC_BSTR(etype);
9936 if(AOP_TYPE(right) == AOP_LIT) {
9937 if((blen == 1) && (bstr < 8)) {
9939 /* it is a single bit, so use the appropriate bit instructions */
9941 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9943 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9944 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9946 pic16_emitpcode(POC_BSF,
9947 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9949 pic16_emitpcode(POC_BCF,
9950 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9956 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9959 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9961 /* if the bit lenth is less than or */
9962 /* it exactly fits a byte then */
9963 if((shCnt=SPEC_BSTR(etype))
9964 || SPEC_BLEN(etype) <= 8 ) {
9966 /* shift left acc */
9969 /* using PRODL as a temporary register here */
9970 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9976 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9977 // pic16_emitcode ("mov","b,a");
9978 // pic16_emitcode("mov","a,@%s",rname);
9982 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9983 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9984 (unsigned char)(0xff >> (8-bstr))) ));
9985 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9986 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9993 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9994 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9999 if ( SPEC_BLEN(etype) <= 8 )
10002 pic16_emitcode("inc","%s",rname);
10003 rLen = SPEC_BLEN(etype) ;
10007 /* now generate for lengths greater than one byte */
10010 l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
10020 pic16_emitcode("mov","@%s,a",rname);
10022 pic16_emitcode("mov","@%s,%s",rname,l);
10027 pic16_emitcode("movx","@dptr,a");
10032 DEBUGpic16_emitcode(";lcall","__gptrput");
10035 pic16_emitcode ("inc","%s",rname);
10040 /* last last was not complete */
10042 /* save the byte & read byte */
10045 pic16_emitcode ("mov","b,a");
10046 pic16_emitcode("mov","a,@%s",rname);
10050 pic16_emitcode ("mov","b,a");
10051 pic16_emitcode("movx","a,@dptr");
10055 pic16_emitcode ("push","b");
10056 pic16_emitcode ("push","acc");
10057 pic16_emitcode ("lcall","__gptrget");
10058 pic16_emitcode ("pop","b");
10062 pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
10063 pic16_emitcode ("orl","a,b");
10066 if (p_type == GPOINTER)
10067 pic16_emitcode("pop","b");
10072 pic16_emitcode("mov","@%s,a",rname);
10076 pic16_emitcode("movx","@dptr,a");
10080 DEBUGpic16_emitcode(";lcall","__gptrput");
10084 /*-----------------------------------------------------------------*/
10085 /* genDataPointerSet - remat pointer to data space */
10086 /*-----------------------------------------------------------------*/
10087 static void genDataPointerSet(operand *right,
10091 int size, offset = 0, resoffset=0 ;
10093 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10094 pic16_aopOp(right,ic,FALSE);
10096 size = AOP_SIZE(right);
10098 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10101 if ( AOP_TYPE(result) == AOP_PCODE) {
10102 fprintf(stderr,"genDataPointerSet %s, %d\n",
10103 AOP(result)->aopu.pcop->name,
10104 (AOP(result)->aopu.pcop->type == PO_DIR)?
10105 PCOR(AOP(result)->aopu.pcop)->instance:
10106 PCOI(AOP(result)->aopu.pcop)->offset);
10110 if(AOP(result)->aopu.pcop->type == PO_DIR)
10111 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
10114 if (AOP_TYPE(right) == AOP_LIT) {
10115 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
10117 lit = lit >> (8*offset);
10119 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
10120 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
10122 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
10125 mov2w(AOP(right), offset);
10126 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
10132 pic16_freeAsmop(right,NULL,ic,TRUE);
10137 /*-----------------------------------------------------------------*/
10138 /* genNearPointerSet - pic16_emitcode for near pointer put */
10139 /*-----------------------------------------------------------------*/
10140 static void genNearPointerSet (operand *right,
10147 sym_link *ptype = operandType(result);
10148 sym_link *resetype;
10150 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10151 retype= getSpec(operandType(right));
10152 resetype = getSpec(operandType(result));
10154 pic16_aopOp(result,ic,FALSE);
10156 /* if the result is rematerializable &
10157 * in data space & not a bit variable */
10159 /* and result is not a bit variable */
10160 if (AOP_TYPE(result) == AOP_PCODE
10161 // && AOP_TYPE(result) == AOP_IMMD
10162 && DCL_TYPE(ptype) == POINTER
10163 && !IS_BITFIELD(retype)
10164 && !IS_BITFIELD(resetype)) {
10166 genDataPointerSet (right,result,ic);
10167 pic16_freeAsmop(result,NULL,ic,TRUE);
10171 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10172 pic16_aopOp(right,ic,FALSE);
10173 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10175 /* if the value is already in a pointer register
10176 * then don't need anything more */
10177 if (!AOP_INPREG(AOP(result))) {
10178 /* otherwise get a free pointer register */
10179 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10181 if( (AOP_TYPE(result) == AOP_PCODE)
10182 && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10183 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10185 pic16_loadFSR0( result ); // patch 10
10187 // set up FSR0 with address of result
10188 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10189 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10194 // rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10196 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10198 /* if bitfield then unpack the bits */
10199 if (IS_BITFIELD(resetype)) {
10200 genPackBits (resetype, right, NULL, POINTER);
10202 /* we have can just get the values */
10203 int size = AOP_SIZE(right);
10206 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10208 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10211 //pic16_emitcode("mov","@%s,a",rname);
10212 pic16_emitcode("movf","indf0,w ;1");
10215 if (AOP_TYPE(right) == AOP_LIT) { // patch 10
10216 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); //
10218 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); //
10220 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); //
10222 } else { // no literal //
10224 pic16_emitpcode(POC_MOVFF, //
10225 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10226 pic16_popCopyReg(&pic16_pc_postinc0))); //
10228 pic16_emitpcode(POC_MOVFF, //
10229 pic16_popGet2p(pic16_popGet(AOP(right),offset), //
10230 pic16_popCopyReg(&pic16_pc_indf0))); //
10238 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10239 /* now some housekeeping stuff */
10241 /* we had to allocate for this iCode */
10242 pic16_freeAsmop(NULL,aop,ic,TRUE);
10244 /* we did not allocate which means left
10245 * already in a pointer register, then
10246 * if size > 0 && this could be used again
10247 * we have to point it back to where it
10249 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10250 if (AOP_SIZE(right) > 1
10251 && !OP_SYMBOL(result)->remat
10252 && ( OP_SYMBOL(result)->liveTo > ic->seq
10255 int size = AOP_SIZE(right) - 1;
10258 pic16_emitcode("decf","fsr0,f");
10259 //pic16_emitcode("dec","%s",rname);
10263 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10266 pic16_freeAsmop(right,NULL,ic,TRUE);
10267 pic16_freeAsmop(result,NULL,ic,TRUE);
10270 /*-----------------------------------------------------------------*/
10271 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
10272 /*-----------------------------------------------------------------*/
10273 static void genPagedPointerSet (operand *right,
10278 regs *preg = NULL ;
10282 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10284 retype= getSpec(operandType(right));
10286 pic16_aopOp(result,ic,FALSE);
10288 /* if the value is already in a pointer register
10289 then don't need anything more */
10290 if (!AOP_INPREG(AOP(result))) {
10291 /* otherwise get a free pointer register */
10293 preg = getFreePtr(ic,&aop,FALSE);
10294 pic16_emitcode("mov","%s,%s",
10296 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10297 rname = preg->name ;
10299 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10301 pic16_freeAsmop(result,NULL,ic,TRUE);
10302 pic16_aopOp (right,ic,FALSE);
10304 /* if bitfield then unpack the bits */
10305 if (IS_BITFIELD(retype))
10306 genPackBits (retype,right,rname,PPOINTER);
10308 /* we have can just get the values */
10309 int size = AOP_SIZE(right);
10313 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10316 pic16_emitcode("movx","@%s,a",rname);
10319 pic16_emitcode("inc","%s",rname);
10325 /* now some housekeeping stuff */
10327 /* we had to allocate for this iCode */
10328 pic16_freeAsmop(NULL,aop,ic,TRUE);
10330 /* we did not allocate which means left
10331 already in a pointer register, then
10332 if size > 0 && this could be used again
10333 we have to point it back to where it
10335 if (AOP_SIZE(right) > 1 &&
10336 !OP_SYMBOL(result)->remat &&
10337 ( OP_SYMBOL(result)->liveTo > ic->seq ||
10339 int size = AOP_SIZE(right) - 1;
10341 pic16_emitcode("dec","%s",rname);
10346 pic16_freeAsmop(right,NULL,ic,TRUE);
10351 /*-----------------------------------------------------------------*/
10352 /* genFarPointerSet - set value from far space */
10353 /*-----------------------------------------------------------------*/
10354 static void genFarPointerSet (operand *right,
10355 operand *result, iCode *ic)
10358 sym_link *retype = getSpec(operandType(right));
10360 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10361 pic16_aopOp(result,ic,FALSE);
10363 /* if the operand is already in dptr
10364 then we do nothing else we move the value to dptr */
10365 if (AOP_TYPE(result) != AOP_STR) {
10366 /* if this is remateriazable */
10367 if (AOP_TYPE(result) == AOP_IMMD)
10368 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10369 else { /* we need to get it byte by byte */
10370 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10371 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10372 if (options.model == MODEL_FLAT24)
10374 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10378 /* so dptr know contains the address */
10379 pic16_freeAsmop(result,NULL,ic,TRUE);
10380 pic16_aopOp(right,ic,FALSE);
10382 /* if bit then unpack */
10383 if (IS_BITFIELD(retype))
10384 genPackBits(retype,right,"dptr",FPOINTER);
10386 size = AOP_SIZE(right);
10390 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10392 pic16_emitcode("movx","@dptr,a");
10394 pic16_emitcode("inc","dptr");
10398 pic16_freeAsmop(right,NULL,ic,TRUE);
10401 /*-----------------------------------------------------------------*/
10402 /* genGenPointerSet - set value from generic pointer space */
10403 /*-----------------------------------------------------------------*/
10404 static void genGenPointerSet (operand *right,
10405 operand *result, iCode *ic)
10407 int i, size, offset, lit;
10408 sym_link *retype = getSpec(operandType(right));
10410 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10412 pic16_aopOp(result,ic,FALSE);
10413 pic16_aopOp(right,ic,FALSE);
10414 size = AOP_SIZE(right);
10417 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10419 /* if the operand is already in dptr
10420 then we do nothing else we move the value to dptr */
10421 if (AOP_TYPE(result) != AOP_STR) {
10422 /* if this is remateriazable */
10423 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10424 // WARNING: anythig until "else" is untested!
10425 if (AOP_TYPE(result) == AOP_IMMD) {
10426 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10427 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10428 // load FSR0 from immediate
10429 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10433 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10435 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10441 else { /* we need to get it byte by byte */
10442 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10443 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10445 // set up FSR0 with address of result
10446 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10447 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10449 /* hack hack! see if this the FSR. If so don't load W */
10450 if(AOP_TYPE(right) != AOP_ACC) {
10452 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10454 if(AOP_TYPE(right) == AOP_LIT)
10457 // note: pic16_popGet handles sign extension
10458 for(i=0;i<size;i++) {
10459 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10461 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10463 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10468 for(i=0;i<size;i++) {
10470 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10471 pic16_popCopyReg(&pic16_pc_postinc0)));
10473 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10474 pic16_popCopyReg(&pic16_pc_indf0)));
10480 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10481 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10483 } // if (AOP_TYPE(result) != AOP_IMMD)
10485 } // if (AOP_TYPE(result) != AOP_STR)
10486 /* so dptr know contains the address */
10489 /* if bit then unpack */
10490 if (IS_BITFIELD(retype))
10491 genPackBits(retype,right,"dptr",GPOINTER);
10493 size = AOP_SIZE(right);
10496 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
10498 // set up FSR0 with address of result
10499 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10500 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10503 if (AOP_TYPE(right) == AOP_LIT) {
10504 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10506 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10508 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10510 } else { // no literal
10512 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10514 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10522 pic16_freeAsmop(right,NULL,ic,TRUE);
10523 pic16_freeAsmop(result,NULL,ic,TRUE);
10526 /*-----------------------------------------------------------------*/
10527 /* genPointerSet - stores the value into a pointer location */
10528 /*-----------------------------------------------------------------*/
10529 static void genPointerSet (iCode *ic)
10531 operand *right, *result ;
10532 sym_link *type, *etype;
10535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10537 right = IC_RIGHT(ic);
10538 result = IC_RESULT(ic) ;
10540 /* depending on the type of pointer we need to
10541 move it to the correct pointer register */
10542 type = operandType(result);
10543 etype = getSpec(type);
10544 /* if left is of type of pointer then it is simple */
10545 if (IS_PTR(type) && !IS_FUNC(type->next)) {
10546 p_type = DCL_TYPE(type);
10549 /* we have to go by the storage class */
10550 p_type = PTR_TYPE(SPEC_OCLS(etype));
10552 /* if (SPEC_OCLS(etype)->codesp ) { */
10553 /* p_type = CPOINTER ; */
10556 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10557 /* p_type = FPOINTER ; */
10559 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10560 /* p_type = PPOINTER ; */
10562 /* if (SPEC_OCLS(etype) == idata ) */
10563 /* p_type = IPOINTER ; */
10565 /* p_type = POINTER ; */
10568 /* now that we have the pointer type we assign
10569 the pointer values */
10574 genNearPointerSet (right,result,ic);
10578 genPagedPointerSet (right,result,ic);
10582 genFarPointerSet (right,result,ic);
10586 genGenPointerSet (right,result,ic);
10590 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10591 "genPointerSet: illegal pointer type");
10595 /*-----------------------------------------------------------------*/
10596 /* genIfx - generate code for Ifx statement */
10597 /*-----------------------------------------------------------------*/
10598 static void genIfx (iCode *ic, iCode *popIc)
10600 operand *cond = IC_COND(ic);
10603 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10605 pic16_aopOp(cond,ic,FALSE);
10607 /* get the value into acc */
10608 if (AOP_TYPE(cond) != AOP_CRY)
10609 pic16_toBoolean(cond);
10612 /* the result is now in the accumulator */
10613 pic16_freeAsmop(cond,NULL,ic,TRUE);
10615 /* if there was something to be popped then do it */
10619 /* if the condition is a bit variable */
10620 if (isbit && IS_ITEMP(cond) &&
10622 genIfxJump(ic,SPIL_LOC(cond)->rname);
10623 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10626 if (isbit && !IS_ITEMP(cond))
10627 genIfxJump(ic,OP_SYMBOL(cond)->rname);
10629 genIfxJump(ic,"a");
10635 /*-----------------------------------------------------------------*/
10636 /* genAddrOf - generates code for address of */
10637 /*-----------------------------------------------------------------*/
10638 static void genAddrOf (iCode *ic)
10640 operand *result, *left;
10642 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
10643 pCodeOp *pcop0, *pcop1, *pcop2;
10645 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10647 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10648 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10650 sym = OP_SYMBOL( left );
10652 size = AOP_SIZE(IC_RESULT(ic));
10656 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
10661 // if(pic16_debug_verbose) {
10662 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10663 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10666 /* Assume that what we want the address of is in data space
10667 * since there is no stack on the PIC, yet! -- VR */
10669 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10672 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10675 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10679 pic16_emitpcode(POC_MOVLW, pcop0);
10680 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10681 pic16_emitpcode(POC_MOVLW, pcop1);
10682 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10683 pic16_emitpcode(POC_MOVLW, pcop2);
10684 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10687 pic16_emitpcode(POC_MOVLW, pcop0);
10688 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10689 pic16_emitpcode(POC_MOVLW, pcop1);
10690 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10692 pic16_emitpcode(POC_MOVLW, pcop0);
10693 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10696 pic16_freeAsmop(result,NULL,ic,TRUE);
10697 pic16_freeAsmop(left, NULL, ic, FALSE);
10702 /*-----------------------------------------------------------------*/
10703 /* genFarFarAssign - assignment when both are in far space */
10704 /*-----------------------------------------------------------------*/
10705 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10707 int size = AOP_SIZE(right);
10710 /* first push the right side on to the stack */
10712 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10714 pic16_emitcode ("push","acc");
10717 pic16_freeAsmop(right,NULL,ic,FALSE);
10718 /* now assign DPTR to result */
10719 pic16_aopOp(result,ic,FALSE);
10720 size = AOP_SIZE(result);
10722 pic16_emitcode ("pop","acc");
10723 pic16_aopPut(AOP(result),"a",--offset);
10725 pic16_freeAsmop(result,NULL,ic,FALSE);
10730 /*-----------------------------------------------------------------*/
10731 /* genAssign - generate code for assignment */
10732 /*-----------------------------------------------------------------*/
10733 static void genAssign (iCode *ic)
10735 operand *result, *right;
10736 int size, offset,know_W;
10737 unsigned long lit = 0L;
10739 result = IC_RESULT(ic);
10740 right = IC_RIGHT(ic) ;
10742 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10744 /* if they are the same */
10745 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10748 pic16_aopOp(right,ic,FALSE);
10749 pic16_aopOp(result,ic,TRUE);
10751 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10753 /* if they are the same registers */
10754 if (pic16_sameRegs(AOP(right),AOP(result)))
10757 /* if the result is a bit */
10758 if (AOP_TYPE(result) == AOP_CRY) {
10759 /* if the right size is a literal then
10760 we know what the value is */
10761 if (AOP_TYPE(right) == AOP_LIT) {
10763 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10764 pic16_popGet(AOP(result),0));
10766 if (((int) operandLitValue(right)))
10767 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10768 AOP(result)->aopu.aop_dir,
10769 AOP(result)->aopu.aop_dir);
10771 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10772 AOP(result)->aopu.aop_dir,
10773 AOP(result)->aopu.aop_dir);
10777 /* the right is also a bit variable */
10778 if (AOP_TYPE(right) == AOP_CRY) {
10779 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10780 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
10781 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10783 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10784 AOP(result)->aopu.aop_dir,
10785 AOP(result)->aopu.aop_dir);
10786 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10787 AOP(right)->aopu.aop_dir,
10788 AOP(right)->aopu.aop_dir);
10789 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10790 AOP(result)->aopu.aop_dir,
10791 AOP(result)->aopu.aop_dir);
10795 /* we need to or */
10796 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
10797 pic16_toBoolean(right);
10799 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
10800 //pic16_aopPut(AOP(result),"a",0);
10804 /* bit variables done */
10806 size = AOP_SIZE(result);
10809 if(AOP_TYPE(right) == AOP_LIT) {
10810 if(!IS_FLOAT(operandType( right )))
10811 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10814 unsigned long lit_int;
10818 /* take care if literal is a float */
10819 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10820 lit = info.lit_int;
10824 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10825 // sizeof(unsigned long int), sizeof(float));
10827 if(AOP_TYPE(right) != AOP_LIT
10828 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10829 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10831 // set up table pointer
10832 if( (AOP_TYPE(right) == AOP_PCODE)
10833 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10834 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10836 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10837 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10838 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10839 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10840 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10841 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10843 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10844 pic16_popCopyReg(&pic16_pc_tblptrl)));
10845 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10846 pic16_popCopyReg(&pic16_pc_tblptrh)));
10847 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10848 pic16_popCopyReg(&pic16_pc_tblptru)));
10851 size = min(AOP_SIZE(right), AOP_SIZE(result));
10853 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10854 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10855 pic16_popGet(AOP(result),offset)));
10859 if(AOP_SIZE(result) > AOP_SIZE(right)) {
10860 size = AOP_SIZE(result) - AOP_SIZE(right);
10862 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10871 /* VR - What is this?! */
10872 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
10873 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10874 if(aopIdx(AOP(result),0) == 4) {
10875 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10877 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10878 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10882 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
10887 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10888 if(AOP_TYPE(right) == AOP_LIT) {
10890 if(know_W != (lit&0xff))
10891 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10893 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10895 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10899 } else if (AOP_TYPE(right) == AOP_CRY) {
10900 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10902 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10903 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10905 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10906 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10907 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10909 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10912 /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10913 normally should work, but mind that the W register live range
10914 is not checked, so if the code generator assumes that the W
10915 is already loaded after such a pair, wrong code will be generated.
10917 Checking the live range is the next step.
10918 This is experimental code yet and has not been fully tested yet.
10919 USE WITH CARE. Revert to old code by setting 0 to the condition above.
10920 Vangelis Rokas 030603 (vrokas@otenet.gr) */
10922 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10924 /* This is the old code, which is assumed(?!) that works fine(!?) */
10926 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10927 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10936 pic16_freeAsmop (right,NULL,ic,FALSE);
10937 pic16_freeAsmop (result,NULL,ic,TRUE);
10940 /*-----------------------------------------------------------------*/
10941 /* genJumpTab - generates code for jump table */
10942 /*-----------------------------------------------------------------*/
10943 static void genJumpTab (iCode *ic)
10948 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10950 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10951 /* get the condition into accumulator */
10952 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10954 /* multiply by three */
10955 pic16_emitcode("add","a,acc");
10956 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10958 jtab = newiTempLabel(NULL);
10959 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10960 pic16_emitcode("jmp","@a+dptr");
10961 pic16_emitcode("","%05d_DS_:",jtab->key+100);
10963 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10964 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10966 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10967 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10968 pic16_emitpLabel(jtab->key);
10970 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10972 /* now generate the jump labels */
10973 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10974 jtab = setNextItem(IC_JTLABELS(ic))) {
10975 pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10976 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10982 /*-----------------------------------------------------------------*/
10983 /* genMixedOperation - gen code for operators between mixed types */
10984 /*-----------------------------------------------------------------*/
10986 TSD - Written for the PIC port - but this unfortunately is buggy.
10987 This routine is good in that it is able to efficiently promote
10988 types to different (larger) sizes. Unfortunately, the temporary
10989 variables that are optimized out by this routine are sometimes
10990 used in other places. So until I know how to really parse the
10991 iCode tree, I'm going to not be using this routine :(.
10993 static int genMixedOperation (iCode *ic)
10996 operand *result = IC_RESULT(ic);
10997 sym_link *ctype = operandType(IC_LEFT(ic));
10998 operand *right = IC_RIGHT(ic);
11004 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
11006 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11012 nextright = IC_RIGHT(nextic);
11013 nextleft = IC_LEFT(nextic);
11014 nextresult = IC_RESULT(nextic);
11016 pic16_aopOp(right,ic,FALSE);
11017 pic16_aopOp(result,ic,FALSE);
11018 pic16_aopOp(nextright, nextic, FALSE);
11019 pic16_aopOp(nextleft, nextic, FALSE);
11020 pic16_aopOp(nextresult, nextic, FALSE);
11022 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
11024 operand *t = right;
11028 pic16_emitcode(";remove right +","");
11030 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
11032 operand *t = right;
11036 pic16_emitcode(";remove left +","");
11040 big = AOP_SIZE(nextleft);
11041 small = AOP_SIZE(nextright);
11043 switch(nextic->op) {
11046 pic16_emitcode(";optimize a +","");
11047 /* if unsigned or not an integral type */
11048 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
11049 pic16_emitcode(";add a bit to something","");
11052 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
11054 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
11055 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
11056 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
11058 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
11066 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11067 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11068 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11071 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11073 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11074 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
11075 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
11076 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11077 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
11080 pic16_emitcode("rlf","known_zero,w");
11087 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11088 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11089 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11091 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11101 pic16_freeAsmop(right,NULL,ic,TRUE);
11102 pic16_freeAsmop(result,NULL,ic,TRUE);
11103 pic16_freeAsmop(nextright,NULL,ic,TRUE);
11104 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
11106 nextic->generated = 1;
11113 /*-----------------------------------------------------------------*/
11114 /* genCast - gen code for casting */
11115 /*-----------------------------------------------------------------*/
11116 static void genCast (iCode *ic)
11118 operand *result = IC_RESULT(ic);
11119 sym_link *ctype = operandType(IC_LEFT(ic));
11120 sym_link *rtype = operandType(IC_RIGHT(ic));
11121 operand *right = IC_RIGHT(ic);
11124 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11125 /* if they are equivalent then do nothing */
11126 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
11129 pic16_aopOp(right,ic,FALSE) ;
11130 pic16_aopOp(result,ic,FALSE);
11132 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11134 /* if the result is a bit */
11135 if (AOP_TYPE(result) == AOP_CRY) {
11137 /* if the right size is a literal then
11138 * we know what the value is */
11139 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11141 if (AOP_TYPE(right) == AOP_LIT) {
11142 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11143 pic16_popGet(AOP(result),0));
11145 if (((int) operandLitValue(right)))
11146 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
11147 AOP(result)->aopu.aop_dir,
11148 AOP(result)->aopu.aop_dir);
11150 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
11151 AOP(result)->aopu.aop_dir,
11152 AOP(result)->aopu.aop_dir);
11156 /* the right is also a bit variable */
11157 if (AOP_TYPE(right) == AOP_CRY) {
11159 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11161 pic16_emitcode("clrc","");
11162 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11163 AOP(right)->aopu.aop_dir,
11164 AOP(right)->aopu.aop_dir);
11165 pic16_aopPut(AOP(result),"c",0);
11169 /* we need to or */
11170 if (AOP_TYPE(right) == AOP_REG) {
11171 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
11172 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
11173 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
11175 pic16_toBoolean(right);
11176 pic16_aopPut(AOP(result),"a",0);
11180 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11183 size = AOP_SIZE(result);
11185 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11187 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
11188 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
11189 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
11192 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11197 /* if they are the same size : or less */
11198 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11200 /* if they are in the same place */
11201 if (pic16_sameRegs(AOP(right),AOP(result)))
11204 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11206 if (IS_PTR_CONST(rtype))
11208 if (IS_CODEPTR(rtype))
11210 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11213 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11215 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11217 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11220 if(AOP_TYPE(right) == AOP_IMMD) {
11221 pCodeOp *pcop0, *pcop1, *pcop2;
11222 symbol *sym = OP_SYMBOL( right );
11224 size = AOP_SIZE(result);
11226 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11228 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11230 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11233 pic16_emitpcode(POC_MOVLW, pcop0);
11234 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11235 pic16_emitpcode(POC_MOVLW, pcop1);
11236 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11237 pic16_emitpcode(POC_MOVLW, pcop2);
11238 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11241 pic16_emitpcode(POC_MOVLW, pcop0);
11242 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11243 pic16_emitpcode(POC_MOVLW, pcop1);
11244 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11246 pic16_emitpcode(POC_MOVLW, pcop0);
11247 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11251 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11252 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11253 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11254 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11255 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11256 if(AOP_SIZE(result) <2)
11257 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11259 /* if they in different places then copy */
11260 size = AOP_SIZE(result);
11263 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11264 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11271 /* if the result is of type pointer */
11272 if (IS_PTR(ctype)) {
11274 sym_link *type = operandType(right);
11275 sym_link *etype = getSpec(type);
11277 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
11279 /* pointer to generic pointer */
11280 if (IS_GENPTR(ctype)) {
11284 p_type = DCL_TYPE(type);
11286 /* we have to go by the storage class */
11287 p_type = PTR_TYPE(SPEC_OCLS(etype));
11289 /* if (SPEC_OCLS(etype)->codesp ) */
11290 /* p_type = CPOINTER ; */
11292 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11293 /* p_type = FPOINTER ; */
11295 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11296 /* p_type = PPOINTER; */
11298 /* if (SPEC_OCLS(etype) == idata ) */
11299 /* p_type = IPOINTER ; */
11301 /* p_type = POINTER ; */
11304 /* the first two bytes are known */
11305 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
11306 size = GPTRSIZE - 1;
11309 if(offset < AOP_SIZE(right)) {
11310 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3",__FUNCTION__,__LINE__);
11311 if ((AOP_TYPE(right) == AOP_PCODE) &&
11312 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11313 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11314 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11316 pic16_aopPut(AOP(result),
11317 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11321 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11324 /* the last byte depending on type */
11328 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11331 pic16_emitcode(";BUG!? ","%d",__LINE__);
11335 pic16_emitcode(";BUG!? ","%d",__LINE__);
11339 pic16_emitcode(";BUG!? ","%d",__LINE__);
11344 /* this should never happen */
11345 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11346 "got unknown pointer type");
11349 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
11353 /* just copy the pointers */
11354 size = AOP_SIZE(result);
11357 pic16_aopPut(AOP(result),
11358 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11367 /* so we now know that the size of destination is greater
11368 than the size of the source.
11369 Now, if the next iCode is an operator then we might be
11370 able to optimize the operation without performing a cast.
11372 if(genMixedOperation(ic))
11375 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
11377 /* we move to result for the size of source */
11378 size = AOP_SIZE(right);
11381 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11382 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11383 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11387 /* now depending on the sign of the destination */
11388 size = AOP_SIZE(result) - AOP_SIZE(right);
11389 /* if unsigned or not an integral type */
11390 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11392 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
11394 /* we need to extend the sign :( */
11397 /* Save one instruction of casting char to int */
11398 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
11399 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11400 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
11402 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11405 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11407 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11409 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
11412 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
11417 pic16_freeAsmop(right,NULL,ic,TRUE);
11418 pic16_freeAsmop(result,NULL,ic,TRUE);
11422 /*-----------------------------------------------------------------*/
11423 /* genDjnz - generate decrement & jump if not zero instrucion */
11424 /*-----------------------------------------------------------------*/
11425 static int genDjnz (iCode *ic, iCode *ifx)
11427 symbol *lbl, *lbl1;
11428 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11433 /* if the if condition has a false label
11434 then we cannot save */
11438 /* if the minus is not of the form
11440 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11441 !IS_OP_LITERAL(IC_RIGHT(ic)))
11444 if (operandLitValue(IC_RIGHT(ic)) != 1)
11447 /* if the size of this greater than one then no
11449 if (getSize(operandType(IC_RESULT(ic))) > 1)
11452 /* otherwise we can save BIG */
11453 lbl = newiTempLabel(NULL);
11454 lbl1= newiTempLabel(NULL);
11456 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11458 if (IS_AOP_PREG(IC_RESULT(ic))) {
11459 pic16_emitcode("dec","%s",
11460 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11461 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11462 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11466 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11467 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11469 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11470 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
11473 /* pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11474 /* pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11475 /* pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11476 /* pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11479 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11480 ifx->generated = 1;
11484 /*-----------------------------------------------------------------*/
11485 /* genReceive - generate code for a receive iCode */
11486 /*-----------------------------------------------------------------*/
11487 static void genReceive (iCode *ic)
11489 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11492 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11493 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
11495 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11497 if (isOperandInFarSpace(IC_RESULT(ic)) &&
11498 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11499 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11501 int size = getSize(operandType(IC_RESULT(ic)));
11502 int offset = pic16_fReturnSizePic - size;
11506 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11507 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11511 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
11513 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11514 size = AOP_SIZE(IC_RESULT(ic));
11517 pic16_emitcode ("pop","acc");
11518 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11521 DEBUGpic16_emitcode ("; ***","2 %s %d",__FUNCTION__,__LINE__);
11524 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11526 assignResultValue(IC_RESULT(ic), 0);
11529 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11532 /*-----------------------------------------------------------------*/
11533 /* genDummyRead - generate code for dummy read of volatiles */
11534 /*-----------------------------------------------------------------*/
11536 genDummyRead (iCode * ic)
11538 pic16_emitcode ("; genDummyRead","");
11539 pic16_emitcode ("; not implemented","");
11544 /*-----------------------------------------------------------------*/
11545 /* genpic16Code - generate code for pic16 based controllers */
11546 /*-----------------------------------------------------------------*/
11548 * At this point, ralloc.c has gone through the iCode and attempted
11549 * to optimize in a way suitable for a PIC. Now we've got to generate
11550 * PIC instructions that correspond to the iCode.
11552 * Once the instructions are generated, we'll pass through both the
11553 * peep hole optimizer and the pCode optimizer.
11554 *-----------------------------------------------------------------*/
11556 void genpic16Code (iCode *lic)
11561 lineHead = lineCurr = NULL;
11563 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11564 pic16_addpBlock(pb);
11567 /* if debug information required */
11568 if (options.debug && currFunc) {
11570 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11575 for (ic = lic ; ic ; ic = ic->next ) {
11577 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11578 if ( cln != ic->lineno ) {
11579 if ( options.debug ) {
11580 debugFile->writeCLine (ic);
11583 if(!options.noCcodeInAsm) {
11584 pic16_addpCode2pBlock(pb,
11585 pic16_newpCodeCSource(ic->lineno, ic->filename,
11586 printCLine(ic->filename, ic->lineno)));
11592 if(options.iCodeInAsm) {
11594 /* insert here code to print iCode as comment */
11595 l = Safe_strdup(printILine(ic));
11596 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11599 /* if the result is marked as
11600 spilt and rematerializable or code for
11601 this has already been generated then
11603 if (resultRemat(ic) || ic->generated )
11606 /* depending on the operation */
11625 /* IPOP happens only when trying to restore a
11626 spilt live range, if there is an ifx statement
11627 following this pop then the if statement might
11628 be using some of the registers being popped which
11629 would destroy the contents of the register so
11630 we need to check for this condition and handle it */
11632 ic->next->op == IFX &&
11633 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
11634 genIfx (ic->next,ic);
11652 genEndFunction (ic);
11668 pic16_genPlus (ic) ;
11672 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11673 pic16_genMinus (ic);
11689 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
11693 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11700 /* note these two are xlated by algebraic equivalence
11701 during parsing SDCC.y */
11702 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11703 "got '>=' or '<=' shouldn't have come here");
11707 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11719 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11723 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11727 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11751 genRightShift (ic);
11754 case GET_VALUE_AT_ADDRESS:
11759 if (POINTER_SET(ic))
11786 addSet(&_G.sendSet,ic);
11789 case DUMMY_READ_VOLATILE:
11799 /* now we are ready to call the
11800 peep hole optimizer */
11801 if (!options.nopeep) {
11802 peepHole (&lineHead);
11804 /* now do the actual printing */
11805 printLine (lineHead,codeOutFile);
11808 DFPRINTF((stderr,"printing pBlock\n\n"));
11809 pic16_printpBlock(stdout,pb);