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,2005)
10 Bug Fixes - Raphael Neider rneider@web.de (2004,2005)
12 This program is free software; you can redistribute it and/or modify it
13 under the terms of the GNU General Public License as published by the
14 Free Software Foundation; either version 2, or (at your option) any
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 In other words, you are welcome to use, share and improve this program.
27 You are forbidden to forbid anyone else to use, share and improve
28 what you give them. Help stamp out software-hoarding!
31 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
32 Made everything static
33 -------------------------------------------------------------------------*/
39 #include "SDCCglobl.h"
43 #include "SDCCpeeph.h"
51 /* Set the following to 1 to enable the slower/bigger
52 * but more robust generic shifting routine (which also
53 * operates correctly with negative shift values). */
54 #define USE_GENERIC_SIGNED_SHIFT 1
56 /* Set the following to 1 to enable the new
57 * stripped down genCmp version.
58 * This version should be easier to understand,
59 * more reliable and (sigh) slighly slower. */
60 #define USE_SIMPLE_GENCMP 1
62 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
63 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
64 #define PIC_IS_FARPTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
66 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
67 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
68 void pic16_genMult8X8_8 (operand *, operand *,operand *);
69 void pic16_genMult16X16_16(operand *, operand *, operand *);
70 void pic16_genMult32X32_32(operand *, operand *, operand *);
71 pCode *pic16_AssembleLine(char *line, int peeps);
72 extern void pic16_printpBlock(FILE *of, pBlock *pb);
73 static asmop *newAsmop (short type);
74 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
75 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
76 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
77 static pCodeOp *pic16_popRegFromIdx(int rIdx);
79 //static int aopIdx (asmop *aop, int offset);
81 int pic16_labelOffset=0;
82 extern int pic16_debug_verbose;
83 #if !(USE_GENERIC_SIGNED_SHIFT)
84 static int optimized_for_speed = 0;
93 /* max_key keeps track of the largest label number used in
94 a function. This is then used to adjust the label offset
95 for the next function.
98 static int GpsuedoStkPtr=0;
100 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
102 unsigned int pic16aopLiteral (value *val, int offset);
103 const char *pic16_AopType(short type);
104 static iCode *ifxForOp ( operand *op, iCode *ic );
106 void pic16_pushpCodeOp(pCodeOp *pcop);
107 void pic16_poppCodeOp(pCodeOp *pcop);
109 static bool is_LitOp(operand *op);
110 static bool is_LitAOp(asmop *aop);
113 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
115 /* set the following macro to 1 to enable passing the
116 * first byte of functions parameters via WREG */
117 #define USE_WREG_IN_FUNC_PARAMS 0
120 /* this is the down and dirty file with all kinds of
121 kludgy & hacky stuff. This is what it is all about
122 CODE GENERATION for a specific MCU . some of the
123 routines may be reusable, will have to see */
125 static char *zero = "#0x00";
126 static char *one = "#0x01";
127 //static char *spname = "sp";
131 * Function return value policy (MSB-->LSB):
133 * 16 bits -> PRODL:WREG
134 * 24 bits -> PRODH:PRODL:WREG
135 * 32 bits -> FSR0L:PRODH:PRODL:WREG
136 * >32 bits -> on stack, and FSR0 points to the beginning
141 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
142 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
143 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
144 static char **fReturn = fReturnpic16;
146 static char *accUse[] = {"WREG"};
148 //static short rbank = -1;
162 bitVect *fregsUsed; /* registers used in function */
164 set *sregsAllocSet; /* registers used to store stack variables */
165 int stack_lat; /* stack offset latency */
167 int useWreg; /* flag when WREG is used to pass function parameter */
170 extern int pic16_ptrRegReq ;
171 extern int pic16_nRegs;
172 extern FILE *codeOutFile;
173 //static void saverbank (int, iCode *,bool);
175 static lineNode *lineHead = NULL;
176 static lineNode *lineCurr = NULL;
178 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
179 0xE0, 0xC0, 0x80, 0x00};
180 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
181 0x07, 0x03, 0x01, 0x00};
185 /*-----------------------------------------------------------------*/
186 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
187 /* exponent of 2 is returned, otherwise -1 is */
189 /* note that this is similar to the function `powof2' in SDCCsymt */
193 /*-----------------------------------------------------------------*/
194 int pic16_my_powof2 (unsigned long num)
197 if( (num & (num-1)) == 0) {
210 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
212 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
214 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
215 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
216 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
217 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
218 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
219 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
220 ((result) ? AOP_SIZE(result) : 0));
223 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
226 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
228 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
229 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
230 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
231 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
232 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
233 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
237 void pic16_emitpcomment (char *fmt, ...)
240 char lb[INITIAL_INLINEASM];
241 unsigned char *lbp = lb;
246 vsprintf(lb+1,fmt,ap);
248 while (isspace(*lbp)) lbp++;
251 lineCurr = (lineCurr ?
252 connectLine(lineCurr,newLineNode(lb)) :
253 (lineHead = newLineNode(lb)));
254 lineCurr->isInline = _G.inLine;
255 lineCurr->isDebug = _G.debugLine;
257 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
260 // fprintf(stderr, "%s\n", lb);
263 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
266 char lb[INITIAL_INLINEASM];
267 unsigned char *lbp = lb;
269 if(!pic16_debug_verbose)
276 sprintf(lb,"%s\t",inst);
278 sprintf(lb,"%s",inst);
279 vsprintf(lb+(strlen(lb)),fmt,ap);
283 while (isspace(*lbp)) lbp++;
286 lineCurr = (lineCurr ?
287 connectLine(lineCurr,newLineNode(lb)) :
288 (lineHead = newLineNode(lb)));
289 lineCurr->isInline = _G.inLine;
290 lineCurr->isDebug = _G.debugLine;
292 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
295 // fprintf(stderr, "%s\n", lb);
300 void pic16_emitpLabel(int key)
302 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
305 void pic16_emitpLabelFORCE(int key)
307 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
310 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
311 * NEVER call pic16_emitpcode_real directly, please... */
312 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
316 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
318 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
321 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
324 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
326 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
329 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
332 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
338 #define pic16_emitcode DEBUGpic16_emitcode
340 /*-----------------------------------------------------------------*/
341 /* pic16_emitcode - writes the code into a file : for now it is simple */
342 /*-----------------------------------------------------------------*/
343 void pic16_emitcode (char *inst,char *fmt, ...)
346 char lb[INITIAL_INLINEASM];
347 unsigned char *lbp = lb;
353 sprintf(lb,"%s\t",inst);
355 sprintf(lb,"%s",inst);
356 vsprintf(lb+(strlen(lb)),fmt,ap);
360 while (isspace(*lbp)) lbp++;
363 lineCurr = (lineCurr ?
364 connectLine(lineCurr,newLineNode(lb)) :
365 (lineHead = newLineNode(lb)));
366 lineCurr->isInline = _G.inLine;
367 lineCurr->isDebug = _G.debugLine;
369 // VR fprintf(stderr, "lb = <%s>\n", lbp);
371 // if(pic16_debug_verbose)
372 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
379 /*-----------------------------------------------------------------*/
380 /* pic16_emitDebuggerSymbol - associate the current code location */
381 /* with a debugger symbol */
382 /*-----------------------------------------------------------------*/
384 pic16_emitDebuggerSymbol (char * debugSym)
387 pic16_emitcode (";", "%s ==.", debugSym);
392 /*-----------------------------------------------------------------*/
393 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
394 /*-----------------------------------------------------------------*/
395 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
397 // bool r0iu = FALSE , r1iu = FALSE;
398 // bool r0ou = FALSE , r1ou = FALSE;
399 bool fsr0iu = FALSE, fsr0ou;
400 bool fsr2iu = FALSE, fsr2ou;
402 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
405 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
406 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
408 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
409 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
411 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
412 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
413 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
416 if(!fsr0iu && !fsr0ou) {
417 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
418 (*aopp)->type = AOP_FSR0;
420 fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
422 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
426 /* no usage of FSR2 */
427 if(!fsr2iu && !fsr2ou) {
428 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
429 (*aopp)->type = AOP_FSR2;
431 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
435 /* now we know they both have usage */
436 /* if fsr0 not used in this instruction */
438 if (!_G.fsr0Pushed) {
439 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
440 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
444 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
445 (*aopp)->type = AOP_FSR0;
447 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
449 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
453 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
458 /* the logic: if r0 & r1 used in the instruction
459 then we are in trouble otherwise */
461 /* first check if r0 & r1 are used by this
462 instruction, in which case we are in trouble */
463 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
464 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
469 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
470 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
472 /* if no usage of r0 then return it */
473 if (!r0iu && !r0ou) {
474 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
475 (*aopp)->type = AOP_R0;
477 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
480 /* if no usage of r1 then return it */
481 if (!r1iu && !r1ou) {
482 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
483 (*aopp)->type = AOP_R1;
485 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
488 /* now we know they both have usage */
489 /* if r0 not used in this instruction */
491 /* push it if not already pushed */
493 //pic16_emitcode ("push","%s",
494 // pic16_regWithIdx(R0_IDX)->dname);
498 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
499 (*aopp)->type = AOP_R0;
501 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
504 /* if r1 not used then */
507 /* push it if not already pushed */
509 //pic16_emitcode ("push","%s",
510 // pic16_regWithIdx(R1_IDX)->dname);
514 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
515 (*aopp)->type = AOP_R1;
516 return pic16_regWithIdx(R1_IDX);
520 /* I said end of world but not quite end of world yet */
521 /* if this is a result then we can push it on the stack*/
523 (*aopp)->type = AOP_STK;
527 /* other wise this is true end of the world */
528 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
529 "getFreePtr should never reach here");
534 /*-----------------------------------------------------------------*/
535 /* newAsmop - creates a new asmOp */
536 /*-----------------------------------------------------------------*/
537 static asmop *newAsmop (short type)
541 aop = Safe_calloc(1,sizeof(asmop));
546 static void genSetDPTR(int n)
550 pic16_emitcode(";", "Select standard DPTR");
551 pic16_emitcode("mov", "dps, #0x00");
555 pic16_emitcode(";", "Select alternate DPTR");
556 pic16_emitcode("mov", "dps, #0x01");
560 /*-----------------------------------------------------------------*/
561 /* resolveIfx - converts an iCode ifx into a form more useful for */
562 /* generating code */
563 /*-----------------------------------------------------------------*/
564 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
568 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
574 resIfx->condition = 1; /* assume that the ifx is true */
575 resIfx->generated = 0; /* indicate that the ifx has not been used */
578 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
581 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
582 __FUNCTION__,__LINE__,resIfx->lbl->key);
587 resIfx->lbl = IC_TRUE(ifx);
589 resIfx->lbl = IC_FALSE(ifx);
590 resIfx->condition = 0;
595 DEBUGpic16_emitcode("; +++","ifx true is non-null");
597 DEBUGpic16_emitcode("; +++","ifx true is null");
599 DEBUGpic16_emitcode("; +++","ifx false is non-null");
601 DEBUGpic16_emitcode("; +++","ifx false is null");
605 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
609 /*-----------------------------------------------------------------*/
610 /* pointerCode - returns the code for a pointer type */
611 /*-----------------------------------------------------------------*/
612 static int pointerCode (sym_link *etype)
615 return PTR_TYPE(SPEC_OCLS(etype));
620 /*-----------------------------------------------------------------*/
621 /* aopForSym - for a true symbol */
622 /*-----------------------------------------------------------------*/
623 static asmop *aopForSym (iCode *ic, operand *op, bool result)
625 symbol *sym=OP_SYMBOL(op);
627 memmap *space= SPEC_OCLS(sym->etype);
631 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
633 // sym = OP_SYMBOL(op);
635 /* if already has one */
637 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
642 /* if symbol was initially placed onStack then we must re-place it
643 * to direct memory, since pic16 does not have a specific stack */
645 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
653 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
655 sym->aop = aop = newAsmop (AOP_PAGED);
656 aop->aopu.aop_dir = sym->rname ;
657 aop->size = getSize(sym->type);
658 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
659 pic16_allocDirReg( IC_LEFT(ic) );
667 /* assign depending on the storage class */
668 /* if it is on the stack or indirectly addressable */
669 /* space we need to assign either r0 or r1 to it */
670 if (sym->onStack) // || sym->iaccess)
675 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
676 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
678 /* acquire a temporary register -- it is saved in function */
680 sym->aop = aop = newAsmop(AOP_STA);
681 aop->aopu.stk.stk = sym->stack;
682 aop->size = getSize(sym->type);
685 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
686 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
687 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
688 // pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
690 for(i=0;i<aop->size;i++)
691 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
692 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
694 if(1 && ic->op == SEND) {
696 /* if SEND do the send here */
699 for(i=0;i<aop->size;i++) {
700 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
701 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
706 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
709 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
711 // we do not need to load the value if it is to be defined...
712 if (result) return aop;
715 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
718 for(i=0;i<aop->size;i++) {
720 /* initialise for stack access via frame pointer */
721 // operands on stack are accessible via "FSR2 + index" with index
722 // starting at 2 for arguments and growing from 0 downwards for
723 // local variables (index == 0 is not assigned so we add one here)
725 int soffs = sym->stack;
731 if(1 && ic->op == SEND) {
732 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
733 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
734 pic16_popCopyReg( pic16_frame_plusw ),
735 pic16_popCopyReg(pic16_stack_postdec )));
737 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
738 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
739 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
745 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
752 /* now assign the address of the variable to
753 the pointer register */
754 if (aop->type != AOP_STK) {
758 pic16_emitcode("push","acc");
760 pic16_emitcode("mov","a,_bp");
761 pic16_emitcode("add","a,#0x%02x",
763 ((char)(sym->stack - _G.nRegsSaved )) :
764 ((char)sym->stack)) & 0xff);
765 pic16_emitcode("mov","%s,a",
766 aop->aopu.aop_ptr->name);
769 pic16_emitcode("pop","acc");
771 pic16_emitcode("mov","%s,#%s",
772 aop->aopu.aop_ptr->name,
774 aop->paged = space->paged;
776 aop->aopu.aop_stk = sym->stack;
784 if (sym->onStack && options.stack10bit)
786 /* It's on the 10 bit stack, which is located in
790 //DEBUGpic16_emitcode(";","%d",__LINE__);
793 pic16_emitcode("push","acc");
795 pic16_emitcode("mov","a,_bp");
796 pic16_emitcode("add","a,#0x%02x",
798 ((char)(sym->stack - _G.nRegsSaved )) :
799 ((char)sym->stack)) & 0xff);
802 pic16_emitcode ("mov","dpx1,#0x40");
803 pic16_emitcode ("mov","dph1,#0x00");
804 pic16_emitcode ("mov","dpl1, a");
808 pic16_emitcode("pop","acc");
810 sym->aop = aop = newAsmop(AOP_DPTR2);
811 aop->size = getSize(sym->type);
817 /* special case for a function */
818 if (IS_FUNC(sym->type)) {
819 sym->aop = aop = newAsmop(AOP_PCODE);
820 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
821 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
822 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
823 PCOI(aop->aopu.pcop)->index = 0;
824 aop->size = FPTRSIZE;
825 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
832 //DEBUGpic16_emitcode(";","%d",__LINE__);
833 /* if in bit space */
834 if (IN_BITSPACE(space)) {
835 sym->aop = aop = newAsmop (AOP_CRY);
836 aop->aopu.aop_dir = sym->rname ;
837 aop->size = getSize(sym->type);
838 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
841 /* if it is in direct space */
842 if (IN_DIRSPACE(space)) {
843 sym->aop = aop = newAsmop (AOP_DIR);
844 aop->aopu.aop_dir = sym->rname ;
845 aop->size = getSize(sym->type);
846 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
847 pic16_allocDirReg( IC_LEFT(ic) );
852 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
853 sym->aop = aop = newAsmop (AOP_DIR);
854 aop->aopu.aop_dir = sym->rname ;
855 aop->size = getSize(sym->type);
856 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
857 pic16_allocDirReg( IC_LEFT(ic) );
862 /* only remaining is far space */
863 sym->aop = aop = newAsmop(AOP_PCODE);
865 /* change the next if to 1 to revert to good old immediate code */
866 if(IN_CODESPACE(space)) {
867 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
868 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
869 PCOI(aop->aopu.pcop)->index = 0;
871 /* try to allocate via direct register */
872 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
873 // aop->size = getSize( sym->type );
876 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
877 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
880 if(!pic16_allocDirReg (IC_LEFT(ic)))
884 if(IN_DIRSPACE( space ))
886 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
887 aop->size = FPTRSIZE;
888 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
889 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
890 else if(sym->onStack) {
893 if(SPEC_SCLS(sym->etype) == S_PDATA) {
894 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
895 aop->size = FPTRSIZE;
900 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
902 /* if it is in code space */
903 if (IN_CODESPACE(space))
909 /*-----------------------------------------------------------------*/
910 /* aopForRemat - rematerialzes an object */
911 /*-----------------------------------------------------------------*/
912 static asmop *aopForRemat (operand *op) // x symbol *sym)
914 symbol *sym = OP_SYMBOL(op);
916 iCode *ic = NULL, *oldic;
917 asmop *aop = newAsmop(AOP_PCODE);
924 ic = sym->rematiCode;
926 if(IS_OP_POINTER(op)) {
927 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
933 // pic16_emitpcomment("ic: %s\n", printILine(ic));
936 val += (int) operandLitValue(IC_RIGHT(ic));
937 } else if (ic->op == '-') {
938 val -= (int) operandLitValue(IC_RIGHT(ic));
942 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
945 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
948 if(!op->isaddr)viaimmd++; else viaimmd=0;
950 /* set the following if to 1 to revert to good old immediate code */
951 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
954 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
956 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
959 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
961 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
964 PCOI(aop->aopu.pcop)->index = val;
966 aop->size = getSize( sym->type );
968 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
970 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
971 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
973 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
977 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
978 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
980 val, IS_PTR_CONST(operandType(op)));
982 val, IS_CODEPTR(operandType(op)));
985 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
987 pic16_allocDirReg (IC_LEFT(ic));
989 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
996 static int aopIdx (asmop *aop, int offset)
1001 if(aop->type != AOP_REG)
1004 return aop->aopu.aop_reg[offset]->rIdx;
1009 /*-----------------------------------------------------------------*/
1010 /* regsInCommon - two operands have some registers in common */
1011 /*-----------------------------------------------------------------*/
1012 static bool regsInCommon (operand *op1, operand *op2)
1014 symbol *sym1, *sym2;
1017 /* if they have registers in common */
1018 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1021 sym1 = OP_SYMBOL(op1);
1022 sym2 = OP_SYMBOL(op2);
1024 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1027 for (i = 0 ; i < sym1->nRegs ; i++) {
1032 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1036 if (sym2->regs[j] == sym1->regs[i])
1044 /*-----------------------------------------------------------------*/
1045 /* operandsEqu - equivalent */
1046 /*-----------------------------------------------------------------*/
1047 static bool operandsEqu ( operand *op1, operand *op2)
1049 symbol *sym1, *sym2;
1051 /* if they not symbols */
1052 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1055 sym1 = OP_SYMBOL(op1);
1056 sym2 = OP_SYMBOL(op2);
1058 /* if both are itemps & one is spilt
1059 and the other is not then false */
1060 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1061 sym1->isspilt != sym2->isspilt )
1064 /* if they are the same */
1068 if (sym1->rname[0] && sym2->rname[0]
1069 && strcmp (sym1->rname, sym2->rname) == 0)
1073 /* if left is a tmp & right is not */
1074 if (IS_ITEMP(op1) &&
1077 (sym1->usl.spillLoc == sym2))
1080 if (IS_ITEMP(op2) &&
1084 (sym2->usl.spillLoc == sym1))
1090 /*-----------------------------------------------------------------*/
1091 /* pic16_sameRegs - two asmops have the same registers */
1092 /*-----------------------------------------------------------------*/
1093 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1100 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1101 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1103 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1105 if (aop1->type != AOP_REG ||
1106 aop2->type != AOP_REG )
1109 /* This is a bit too restrictive if one is a subset of the other...
1110 if (aop1->size != aop2->size )
1114 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1115 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1117 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1118 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1125 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1127 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1128 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1130 if(aop1 == aop2)return TRUE;
1131 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1133 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1139 /*-----------------------------------------------------------------*/
1140 /* pic16_aopOp - allocates an asmop for an operand : */
1141 /*-----------------------------------------------------------------*/
1142 void pic16_aopOp (operand *op, iCode *ic, bool result)
1151 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1153 /* if this a literal */
1154 if (IS_OP_LITERAL(op)) {
1155 op->aop = aop = newAsmop(AOP_LIT);
1156 aop->aopu.aop_lit = op->operand.valOperand;
1157 aop->size = getSize(operandType(op));
1162 sym_link *type = operandType(op);
1164 if(IS_PTR_CONST(type))
1166 if(IS_CODEPTR(type))
1168 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1171 /* if already has a asmop then continue */
1175 /* if the underlying symbol has a aop */
1176 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1177 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1178 op->aop = OP_SYMBOL(op)->aop;
1182 /* if this is a true symbol */
1183 if (IS_TRUE_SYMOP(op)) {
1184 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1185 op->aop = aopForSym(ic, op, result);
1189 /* this is a temporary : this has
1195 e) can be a return use only */
1197 sym = OP_SYMBOL(op);
1199 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1200 /* if the type is a conditional */
1201 if (sym->regType == REG_CND) {
1202 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1207 /* if it is spilt then two situations
1209 b) has a spill location */
1210 if (sym->isspilt || sym->nRegs == 0) {
1212 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1213 DEBUGpic16_emitcode(";","%d",__LINE__);
1214 /* rematerialize it NOW */
1217 sym->aop = op->aop = aop = aopForRemat (op);
1218 // aop->size = getSize(sym->type);
1219 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1226 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1227 aop->size = getSize(sym->type);
1228 for ( i = 0 ; i < 1 ; i++ ) {
1229 aop->aopu.aop_str[i] = accUse[i];
1230 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1232 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1233 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1241 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1242 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1243 //pic16_allocDirReg (IC_LEFT(ic));
1244 aop->size = getSize(sym->type);
1249 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1250 aop->size = getSize(sym->type);
1251 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1252 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1254 DEBUGpic16_emitcode(";","%d",__LINE__);
1258 /* else spill location */
1259 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1260 /* force a new aop if sizes differ */
1261 sym->usl.spillLoc->aop = NULL;
1265 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1266 __FUNCTION__,__LINE__,
1267 sym->usl.spillLoc->rname,
1268 sym->rname, sym->usl.spillLoc->offset);
1271 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1272 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1273 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1274 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1276 sym->usl.spillLoc->offset, op);
1278 fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1279 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1280 assert (getSize(sym->type) <= 1);
1281 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1283 aop->size = getSize(sym->type);
1289 sym_link *type = operandType(op);
1291 if(IS_PTR_CONST(type))
1293 if(IS_CODEPTR(type))
1295 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1298 /* must be in a register */
1299 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1300 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1301 aop->size = sym->nRegs;
1302 for ( i = 0 ; i < sym->nRegs ;i++)
1303 aop->aopu.aop_reg[i] = sym->regs[i];
1306 /*-----------------------------------------------------------------*/
1307 /* pic16_freeAsmop - free up the asmop given to an operand */
1308 /*----------------------------------------------------------------*/
1309 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1326 /* depending on the asmop type only three cases need work AOP_RO
1327 , AOP_R1 && AOP_STK */
1329 switch (aop->type) {
1331 if (_G.fsr0Pushed ) {
1333 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1334 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1335 // pic16_emitcode ("pop","ar0");
1339 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1343 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1349 pic16_emitcode ("pop","ar0");
1353 bitVectUnSetBit(ic->rUsed,R0_IDX);
1359 pic16_emitcode ("pop","ar1");
1363 bitVectUnSetBit(ic->rUsed,R1_IDX);
1370 /* we must store the result on stack */
1371 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1372 // operands on stack are accessible via "FSR2 + index" with index
1373 // starting at 2 for arguments and growing from 0 downwards for
1374 // local variables (index == 0 is not assigned so we add one here)
1375 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1380 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1381 for(i=0;i<aop->size;i++) {
1382 /* initialise for stack access via frame pointer */
1383 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1384 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1385 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1388 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1392 for(i=0;i<aop->size;i++) {
1393 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1395 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1396 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1407 int stk = aop->aopu.aop_stk + aop->size;
1408 bitVectUnSetBit(ic->rUsed,R0_IDX);
1409 bitVectUnSetBit(ic->rUsed,R1_IDX);
1411 getFreePtr(ic,&aop,FALSE);
1413 if (options.stack10bit)
1415 /* I'm not sure what to do here yet... */
1418 "*** Warning: probably generating bad code for "
1419 "10 bit stack mode.\n");
1423 pic16_emitcode ("mov","a,_bp");
1424 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1425 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1427 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1431 pic16_emitcode("pop","acc");
1432 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1434 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1437 pic16_freeAsmop(op,NULL,ic,TRUE);
1439 pic16_emitcode("pop","ar0");
1444 pic16_emitcode("pop","ar1");
1454 /* all other cases just dealloc */
1458 OP_SYMBOL(op)->aop = NULL;
1459 /* if the symbol has a spill */
1461 SPIL_LOC(op)->aop = NULL;
1466 /*-----------------------------------------------------------------*/
1467 /* pic16_aopGet - for fetching value of the aop */
1468 /*-----------------------------------------------------------------*/
1469 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1474 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1476 /* offset is greater than size then zero */
1477 if (offset > (aop->size - 1) &&
1478 aop->type != AOP_LIT)
1481 /* depending on type */
1482 switch (aop->type) {
1486 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1487 rs = Safe_calloc(1, strlen(s)+1);
1492 /* if we need to increment it */
1493 while (offset > aop->coff)
1495 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1499 while (offset < aop->coff)
1501 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1507 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1508 return (dname ? "acc" : "a");
1510 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1511 rs = Safe_calloc (1, strlen (s) + 1);
1519 sprintf (s,"%s",aop->aopu.aop_immd);
1522 sprintf(s,"(%s >> %d)",
1527 aop->aopu.aop_immd);
1528 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1529 rs = Safe_calloc(1,strlen(s)+1);
1535 sprintf(s,"(%s + %d)",
1538 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1540 sprintf(s,"%s",aop->aopu.aop_dir);
1541 rs = Safe_calloc(1,strlen(s)+1);
1547 // return aop->aopu.aop_reg[offset]->dname;
1549 return aop->aopu.aop_reg[offset]->name;
1552 //pic16_emitcode(";","%d",__LINE__);
1553 return aop->aopu.aop_dir;
1556 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1557 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1559 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1560 rs = Safe_strdup("WREG");
1564 sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1565 rs = Safe_calloc(1,strlen(s)+1);
1570 aop->coff = offset ;
1572 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1575 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1576 aop->type = AOP_ACC;
1577 return Safe_strdup("WREG");
1579 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1581 return aop->aopu.aop_str[offset];
1585 pCodeOp *pcop = aop->aopu.pcop;
1586 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1588 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1589 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1591 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1593 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1596 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1599 rs = Safe_calloc(1,strlen(s)+1);
1605 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1607 sprintf(s,"(%s + %d)",
1611 sprintf(s,"%s",aop->aopu.aop_dir);
1612 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1613 rs = Safe_calloc(1,strlen(s)+1);
1619 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1623 // pCodeOp *pcop = aop->aop
1628 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1629 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1630 "aopget got unsupported aop->type");
1636 /* lock has the following meaning: When allocating temporary registers
1637 * for stack variables storage, the value of the temporary register is
1638 * saved on stack. Its value is restored at the end. This procedure is
1639 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1640 * a possibility that before a call to pic16_aopOp, a temporary register
1641 * is allocated for a while and it is freed after some time, this will
1642 * mess the stack and values will not be restored properly. So use lock=1
1643 * to allocate temporary registers used internally by the programmer, and
1644 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1645 * to inform the compiler developer about a possible bug. This is an internal
1646 * feature for developing the compiler -- VR */
1648 int _TempReg_lock = 0;
1649 /*-----------------------------------------------------------------*/
1650 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1651 /*-----------------------------------------------------------------*/
1652 pCodeOp *pic16_popGetTempReg(int lock)
1657 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1659 // werror(W_POSSBUG2, __FILE__, __LINE__);
1662 _TempReg_lock += lock;
1667 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1668 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1669 PCOR(pcop)->r->wasUsed=1;
1670 PCOR(pcop)->r->isFree=0;
1672 /* push value on stack */
1673 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1681 /*-----------------------------------------------------------------*/
1682 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1683 /* is not part of f, but don't save if */
1685 /*-----------------------------------------------------------------*/
1686 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1692 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1695 // werror(W_POSSBUG2, __FILE__, __LINE__);
1698 _TempReg_lock += lock;
1703 i = bitVectFirstBit(f);
1706 /* bypass registers that are used by function */
1707 if(!bitVectBitValue(f, i)) {
1709 /* bypass registers that are already allocated for stack access */
1710 if(!bitVectBitValue(v, i)) {
1712 // debugf("getting register rIdx = %d\n", i);
1713 /* ok, get the operand */
1714 pcop = pic16_newpCodeOpReg( i );
1716 /* should never by NULL */
1717 assert( pcop != NULL );
1721 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1724 PCOR(pcop)->r->wasUsed=1;
1725 PCOR(pcop)->r->isFree=0;
1731 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1733 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1734 /* already used in previous steps, break */
1741 /* caller takes care of the following */
1742 // bitVectSetBit(v, i);
1745 /* push value on stack */
1746 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1747 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1763 /*-----------------------------------------------------------------*/
1764 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1765 /*-----------------------------------------------------------------*/
1766 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1768 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1770 _TempReg_lock -= lock;
1772 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1773 PCOR(pcop)->r->isFree = 1;
1775 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1778 /*-----------------------------------------------------------------*/
1779 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1780 /*-----------------------------------------------------------------*/
1781 pCodeOp *pic16_popGetLabel(unsigned int key)
1784 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1789 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1792 /*-----------------------------------------------------------------*/
1793 /* pic16_popCopyReg - copy a pcode operator */
1794 /*-----------------------------------------------------------------*/
1795 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1799 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1800 memcpy (pcor, pc, sizeof (pCodeOpReg));
1801 pcor->r->wasUsed = 1;
1803 //pcor->pcop.type = pc->pcop.type;
1805 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1806 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1808 pcor->pcop.name = NULL;
1811 //pcor->rIdx = pc->rIdx;
1812 //pcor->r->wasUsed=1;
1813 //pcor->instance = pc->instance;
1815 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1820 /*-----------------------------------------------------------------*/
1821 /* pic16_popGetLit - asm operator to pcode operator conversion */
1822 /*-----------------------------------------------------------------*/
1823 pCodeOp *pic16_popGetLit(int lit)
1825 return pic16_newpCodeOpLit(lit);
1828 /*-----------------------------------------------------------------*/
1829 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1830 /*-----------------------------------------------------------------*/
1831 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1833 return pic16_newpCodeOpLit2(lit, arg2);
1837 /*-----------------------------------------------------------------*/
1838 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1839 /*-----------------------------------------------------------------*/
1840 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1842 return pic16_newpCodeOpImmd(name, offset,index, 0);
1846 /*-----------------------------------------------------------------*/
1847 /* pic16_popGet - asm operator to pcode operator conversion */
1848 /*-----------------------------------------------------------------*/
1849 pCodeOp *pic16_popGetWithString(char *str)
1855 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1859 pcop = pic16_newpCodeOp(str,PO_STR);
1864 /*-----------------------------------------------------------------*/
1865 /* pic16_popRegFromString - */
1866 /*-----------------------------------------------------------------*/
1867 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1870 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1871 pcop->type = PO_DIR;
1873 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1874 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1879 pcop->name = Safe_calloc(1,strlen(str)+1);
1880 strcpy(pcop->name,str);
1882 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1884 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1886 /* make sure that register doesn't exist,
1887 * and operand isn't NULL
1888 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1889 if((PCOR(pcop)->r == NULL)
1891 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1892 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1893 // __FUNCTION__, __LINE__, str, size, offset);
1895 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1896 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1899 PCOR(pcop)->instance = offset;
1904 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1908 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1910 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1911 PCOR(pcop)->rIdx = rIdx;
1912 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1914 PCOR(pcop)->r->isFree = 0;
1915 PCOR(pcop)->r->wasUsed = 1;
1917 pcop->type = PCOR(pcop)->r->pc_type;
1922 /*---------------------------------------------------------------------------------*/
1923 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1925 /*---------------------------------------------------------------------------------*/
1926 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1931 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1933 /* comment the following check, so errors to throw up */
1934 // if(!pcop2)return NULL;
1936 temp = pic16_popGet(aop_dst, offset);
1937 pcop2->pcop2 = temp;
1944 /*--------------------------------------------------------------------------------.-*/
1945 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1946 /* VR 030601 , adapted by Hans Dorn */
1947 /*--------------------------------------------------------------------------------.-*/
1948 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1952 pcop2 = (pCodeOpReg2 *)src;
1960 /*---------------------------------------------------------------------------------*/
1961 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1962 /* movff instruction */
1963 /*---------------------------------------------------------------------------------*/
1964 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1969 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1970 pcop2->pcop2 = pic16_popCopyReg(dst);
1972 /* the pCodeOp may be already allocated */
1973 pcop2 = (pCodeOpReg2 *)(src);
1974 pcop2->pcop2 = (pCodeOp *)(dst);
1981 /*-----------------------------------------------------------------*/
1982 /* pic16_popGet - asm operator to pcode operator conversion */
1983 /*-----------------------------------------------------------------*/
1984 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1986 //char *s = buffer ;
1991 /* offset is greater than
1994 // if (offset > (aop->size - 1) &&
1995 // aop->type != AOP_LIT)
1996 // return NULL; //zero;
1998 /* depending on type */
1999 switch (aop->type) {
2005 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2006 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2013 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2014 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2015 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2016 PCOR(pcop)->r->wasUsed = 1;
2017 PCOR(pcop)->r->isFree = 0;
2019 PCOR(pcop)->instance = offset;
2020 pcop->type = PCOR(pcop)->r->pc_type;
2024 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2025 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2028 /* pCodeOp is already allocated from aopForSym */
2029 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2030 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2036 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2038 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2040 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2042 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2043 PCOR(pcop)->rIdx = rIdx;
2044 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2045 PCOR(pcop)->r->wasUsed=1;
2046 PCOR(pcop)->r->isFree=0;
2048 PCOR(pcop)->instance = offset;
2049 pcop->type = PCOR(pcop)->r->pc_type;
2050 // rs = aop->aopu.aop_reg[offset]->name;
2051 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2055 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2056 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2062 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2063 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2067 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2068 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2074 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2075 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2077 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2079 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2080 // pcop->type = PO_GPR_REGISTER;
2081 PCOR(pcop)->rIdx = rIdx;
2082 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2083 PCOR(pcop)->r->wasUsed=1;
2084 PCOR(pcop)->r->isFree=0;
2086 PCOR(pcop)->instance = offset;
2087 pcop->type = PCOR(pcop)->r->pc_type;
2089 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2090 rs = aop->aopu.aop_reg[offset]->name;
2091 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2096 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2098 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2099 PCOR(pcop)->instance = offset;
2100 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2101 //if(PCOR(pcop)->r == NULL)
2102 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2106 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2107 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2110 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2111 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2114 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2115 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2116 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2117 pcop->type = PCOR(pcop)->r->pc_type;
2118 pcop->name = PCOR(pcop)->r->name;
2124 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2126 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2127 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2128 switch( aop->aopu.pcop->type ) {
2129 case PO_DIR: PCOR(pcop)->instance += offset; break;
2130 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2135 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2136 assert( 0 ); /* should never reach here */;
2141 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2142 "pic16_popGet got unsupported aop->type");
2145 /*-----------------------------------------------------------------*/
2146 /* pic16_aopPut - puts a string for a aop */
2147 /*-----------------------------------------------------------------*/
2148 void pic16_aopPut (asmop *aop, char *s, int offset)
2155 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2157 if (aop->size && offset > ( aop->size - 1)) {
2158 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2159 "pic16_aopPut got offset > aop->size");
2163 /* will assign value to value */
2164 /* depending on where it is ofcourse */
2165 switch (aop->type) {
2168 sprintf(d,"(%s + %d)",
2169 aop->aopu.aop_dir,offset);
2170 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2173 sprintf(d,"%s",aop->aopu.aop_dir);
2176 DEBUGpic16_emitcode(";","%d",__LINE__);
2178 pic16_emitcode("movf","%s,w",s);
2179 pic16_emitcode("movwf","%s",d);
2182 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2183 if(offset >= aop->size) {
2184 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2187 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2190 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2197 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2198 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2201 strcmp(s,"r0") == 0 ||
2202 strcmp(s,"r1") == 0 ||
2203 strcmp(s,"r2") == 0 ||
2204 strcmp(s,"r3") == 0 ||
2205 strcmp(s,"r4") == 0 ||
2206 strcmp(s,"r5") == 0 ||
2207 strcmp(s,"r6") == 0 ||
2208 strcmp(s,"r7") == 0 )
2209 pic16_emitcode("mov","%s,%s ; %d",
2210 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2214 if(strcmp(s,"W")==0 )
2215 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2217 pic16_emitcode("movwf","%s",
2218 aop->aopu.aop_reg[offset]->name);
2220 if(strcmp(s,zero)==0) {
2221 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2223 } else if(strcmp(s,"W")==0) {
2224 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2225 pcop->type = PO_GPR_REGISTER;
2227 PCOR(pcop)->rIdx = -1;
2228 PCOR(pcop)->r = NULL;
2230 DEBUGpic16_emitcode(";","%d",__LINE__);
2231 pcop->name = Safe_strdup(s);
2232 pic16_emitpcode(POC_MOVFW,pcop);
2233 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2234 } else if(strcmp(s,one)==0) {
2235 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2236 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2238 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2246 if (aop->type == AOP_DPTR2)
2252 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2253 "pic16_aopPut writting to code space");
2257 while (offset > aop->coff) {
2259 pic16_emitcode ("inc","dptr");
2262 while (offset < aop->coff) {
2264 pic16_emitcode("lcall","__decdptr");
2269 /* if not in accumulater */
2272 pic16_emitcode ("movx","@dptr,a");
2274 if (aop->type == AOP_DPTR2)
2282 while (offset > aop->coff) {
2284 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2286 while (offset < aop->coff) {
2288 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2294 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2299 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2301 if (strcmp(s,"r0") == 0 ||
2302 strcmp(s,"r1") == 0 ||
2303 strcmp(s,"r2") == 0 ||
2304 strcmp(s,"r3") == 0 ||
2305 strcmp(s,"r4") == 0 ||
2306 strcmp(s,"r5") == 0 ||
2307 strcmp(s,"r6") == 0 ||
2308 strcmp(s,"r7") == 0 ) {
2310 sprintf(buffer,"a%s",s);
2311 pic16_emitcode("mov","@%s,%s",
2312 aop->aopu.aop_ptr->name,buffer);
2314 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2319 if (strcmp(s,"a") == 0)
2320 pic16_emitcode("push","acc");
2322 pic16_emitcode("push","%s",s);
2327 /* if bit variable */
2328 if (!aop->aopu.aop_dir) {
2329 pic16_emitcode("clr","a");
2330 pic16_emitcode("rlc","a");
2333 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2336 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2339 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2341 lbl = newiTempLabel(NULL);
2343 if (strcmp(s,"a")) {
2346 pic16_emitcode("clr","c");
2347 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2348 pic16_emitcode("cpl","c");
2349 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2350 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2357 if (strcmp(aop->aopu.aop_str[offset],s))
2358 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2363 if (!offset && (strcmp(s,"acc") == 0))
2366 if (strcmp(aop->aopu.aop_str[offset],s))
2367 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2371 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2372 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2373 // "pic16_aopPut got unsupported aop->type");
2379 /*-----------------------------------------------------------------*/
2380 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2381 /*-----------------------------------------------------------------*/
2382 void pic16_mov2w (asmop *aop, int offset)
2384 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2387 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2389 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2392 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2394 if(is_LitAOp(src)) {
2395 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2396 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2398 if(pic16_sameRegsOfs(src, dst, offset))return;
2399 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2400 pic16_popGet(dst, offset)));
2404 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2406 if(is_LitAOp(src)) {
2407 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2408 pic16_emitpcode(POC_MOVWF, dst);
2410 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2414 void pic16_testStackOverflow(void)
2416 #define GSTACK_TEST_NAME "_gstack_test"
2418 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2423 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2424 sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2425 // strcpy(sym->rname, GSTACK_TEST_NAME);
2426 checkAddSym(&externs, sym);
2431 /* push pcop into stack */
2432 void pic16_pushpCodeOp(pCodeOp *pcop)
2434 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2435 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2436 if(pic16_options.gstack)
2437 pic16_testStackOverflow();
2441 /* pop pcop from stack */
2442 void pic16_poppCodeOp(pCodeOp *pcop)
2444 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2445 if(pic16_options.gstack)
2446 pic16_testStackOverflow();
2450 /*-----------------------------------------------------------------*/
2451 /* pushw - pushes wreg to stack */
2452 /*-----------------------------------------------------------------*/
2455 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2456 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2457 if(pic16_options.gstack)
2458 pic16_testStackOverflow();
2462 /*-----------------------------------------------------------------*/
2463 /* pushaop - pushes aop to stack */
2464 /*-----------------------------------------------------------------*/
2465 void pushaop(asmop *aop, int offset)
2467 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2469 if(is_LitAOp(aop)) {
2470 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2471 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2473 pic16_emitpcode(POC_MOVFF,
2474 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2477 if(pic16_options.gstack)
2478 pic16_testStackOverflow();
2481 /*-----------------------------------------------------------------*/
2482 /* popaop - pops aop from stack */
2483 /*-----------------------------------------------------------------*/
2484 void popaop(asmop *aop, int offset)
2486 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2487 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2488 if(pic16_options.gstack)
2489 pic16_testStackOverflow();
2492 void popaopidx(asmop *aop, int offset, int index)
2496 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2498 if(STACK_MODEL_LARGE)ofs++;
2500 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2501 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2502 if(pic16_options.gstack)
2503 pic16_testStackOverflow();
2506 #if !(USE_GENERIC_SIGNED_SHIFT)
2507 /*-----------------------------------------------------------------*/
2508 /* reAdjustPreg - points a register back to where it should */
2509 /*-----------------------------------------------------------------*/
2510 static void reAdjustPreg (asmop *aop)
2514 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2516 if ((size = aop->size) <= 1)
2519 switch (aop->type) {
2523 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2527 if (aop->type == AOP_DPTR2)
2533 pic16_emitcode("lcall","__decdptr");
2536 if (aop->type == AOP_DPTR2)
2548 /*-----------------------------------------------------------------*/
2549 /* opIsGptr: returns non-zero if the passed operand is */
2550 /* a generic pointer type. */
2551 /*-----------------------------------------------------------------*/
2552 static int opIsGptr(operand *op)
2554 sym_link *type = operandType(op);
2556 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2557 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2565 /*-----------------------------------------------------------------*/
2566 /* pic16_getDataSize - get the operand data size */
2567 /*-----------------------------------------------------------------*/
2568 int pic16_getDataSize(operand *op)
2570 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2573 return AOP_SIZE(op);
2575 // tsd- in the pic port, the genptr size is 1, so this code here
2576 // fails. ( in the 8051 port, the size was 4).
2579 size = AOP_SIZE(op);
2580 if (size == GPTRSIZE)
2582 sym_link *type = operandType(op);
2583 if (IS_GENPTR(type))
2585 /* generic pointer; arithmetic operations
2586 * should ignore the high byte (pointer type).
2589 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2596 /*-----------------------------------------------------------------*/
2597 /* pic16_outAcc - output Acc */
2598 /*-----------------------------------------------------------------*/
2599 void pic16_outAcc(operand *result)
2602 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2603 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2606 size = pic16_getDataSize(result);
2608 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2611 /* unsigned or positive */
2613 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2618 /*-----------------------------------------------------------------*/
2619 /* pic16_outBitC - output a bit C */
2620 /* Move to result the value of Carry flag -- VR */
2621 /*-----------------------------------------------------------------*/
2622 void pic16_outBitC(operand *result)
2626 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2628 /* if the result is bit */
2629 if (AOP_TYPE(result) == AOP_CRY) {
2630 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2631 pic16_aopPut(AOP(result),"c",0);
2634 i = AOP_SIZE(result);
2636 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2638 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2642 /*-----------------------------------------------------------------*/
2643 /* pic16_outBitOp - output a bit from Op */
2644 /* Move to result the value of set/clr op -- VR */
2645 /*-----------------------------------------------------------------*/
2646 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2650 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2652 /* if the result is bit */
2653 if (AOP_TYPE(result) == AOP_CRY) {
2654 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2655 pic16_aopPut(AOP(result),"c",0);
2658 i = AOP_SIZE(result);
2660 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2662 pic16_emitpcode(POC_RRCF, pcop);
2663 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2667 /*-----------------------------------------------------------------*/
2668 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2669 /*-----------------------------------------------------------------*/
2670 void pic16_toBoolean(operand *oper)
2672 int size = AOP_SIZE(oper) - 1;
2675 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2677 if ( AOP_TYPE(oper) != AOP_ACC) {
2678 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2681 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2685 /*-----------------------------------------------------------------*/
2686 /* genUminusFloat - unary minus for floating points */
2687 /*-----------------------------------------------------------------*/
2688 static void genUminusFloat(operand *op,operand *result)
2690 int size ,offset =0 ;
2693 /* for this we just need to flip the
2694 first it then copy the rest in place */
2695 size = AOP_SIZE(op);
2696 assert( size == AOP_SIZE(result) );
2699 pic16_mov2f(AOP(result), AOP(op), offset);
2703 /* toggle the MSB's highest bit */
2704 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2707 /*-----------------------------------------------------------------*/
2708 /* genUminus - unary minus code generation */
2709 /*-----------------------------------------------------------------*/
2710 static void genUminus (iCode *ic)
2713 sym_link *optype, *rtype;
2720 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2721 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2723 /* if both in bit space then special case */
2724 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2725 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2727 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2728 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2729 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2733 optype = operandType(IC_LEFT(ic));
2734 rtype = operandType(IC_RESULT(ic));
2737 /* if float then do float stuff */
2738 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2739 if(IS_FIXED(optype))
2740 debugf("implement fixed16x16 type\n", 0);
2742 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2746 /* otherwise subtract from zero by taking the 2's complement */
2747 size = AOP_SIZE(IC_LEFT(ic));
2748 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2749 label = newiTempLabel ( NULL );
2751 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2752 for (i=size-1; i > 0; i--) {
2753 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2755 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2756 for (i=1; i < size; i++) {
2757 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2758 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2761 for (i=size-1; i >= 0; i--) {
2762 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2763 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2766 for (i=0; i < size-2; i++) {
2767 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2768 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2770 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2772 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2775 pic16_emitpLabel (label->key);
2778 /* release the aops */
2779 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2780 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2784 /*-----------------------------------------------------------------*/
2785 /* saveRegisters - will look for a call and save the registers */
2786 /*-----------------------------------------------------------------*/
2787 static void saveRegisters(iCode *lic)
2794 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2796 for (ic = lic ; ic ; ic = ic->next)
2797 if (ic->op == CALL || ic->op == PCALL)
2801 fprintf(stderr,"found parameter push with no function call\n");
2805 /* if the registers have been saved already then
2807 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2810 /* find the registers in use at this time
2811 and push them away to safety */
2812 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2816 if (options.useXstack) {
2817 if (bitVectBitValue(rsave,R0_IDX))
2818 pic16_emitcode("mov","b,r0");
2819 pic16_emitcode("mov","r0,%s",spname);
2820 for (i = 0 ; i < pic16_nRegs ; i++) {
2821 if (bitVectBitValue(rsave,i)) {
2823 pic16_emitcode("mov","a,b");
2825 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2826 pic16_emitcode("movx","@r0,a");
2827 pic16_emitcode("inc","r0");
2830 pic16_emitcode("mov","%s,r0",spname);
2831 if (bitVectBitValue(rsave,R0_IDX))
2832 pic16_emitcode("mov","r0,b");
2834 //for (i = 0 ; i < pic16_nRegs ; i++) {
2835 // if (bitVectBitValue(rsave,i))
2836 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2839 dtype = operandType(IC_LEFT(ic));
2840 if (currFunc && dtype &&
2841 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2842 IFFUNC_ISISR(currFunc->type) &&
2845 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2848 /*-----------------------------------------------------------------*/
2849 /* unsaveRegisters - pop the pushed registers */
2850 /*-----------------------------------------------------------------*/
2851 static void unsaveRegisters (iCode *ic)
2856 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2857 /* find the registers in use at this time
2858 and push them away to safety */
2859 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2862 if (options.useXstack) {
2863 pic16_emitcode("mov","r0,%s",spname);
2864 for (i = pic16_nRegs ; i >= 0 ; i--) {
2865 if (bitVectBitValue(rsave,i)) {
2866 pic16_emitcode("dec","r0");
2867 pic16_emitcode("movx","a,@r0");
2869 pic16_emitcode("mov","b,a");
2871 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2875 pic16_emitcode("mov","%s,r0",spname);
2876 if (bitVectBitValue(rsave,R0_IDX))
2877 pic16_emitcode("mov","r0,b");
2879 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2880 // if (bitVectBitValue(rsave,i))
2881 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2888 /*-----------------------------------------------------------------*/
2890 /*-----------------------------------------------------------------*/
2891 static void pushSide(operand * oper, int size)
2894 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2896 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2897 if (AOP_TYPE(oper) != AOP_REG &&
2898 AOP_TYPE(oper) != AOP_DIR &&
2900 pic16_emitcode("mov","a,%s",l);
2901 pic16_emitcode("push","acc");
2903 pic16_emitcode("push","%s",l);
2908 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2910 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2911 pic16_emitpcode(POC_MOVFW, src);
2912 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2914 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2915 src, pic16_popGet(AOP(op), offset)));
2920 /*-----------------------------------------------------------------*/
2921 /* assignResultValue - assign results to oper, rescall==1 is */
2922 /* called from genCall() or genPcall() */
2923 /*-----------------------------------------------------------------*/
2924 static void assignResultValue(operand * oper, int rescall)
2926 int size = AOP_SIZE(oper);
2930 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2931 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2934 /* assign result from a call/pcall function() */
2936 /* function results are stored in a special order,
2937 * see top of file with Function return policy, or manual */
2940 /* 8-bits, result in WREG */
2941 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2944 /* 16-bits, result in PRODL:WREG */
2945 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2949 /* 24-bits, result in PRODH:PRODL:WREG */
2950 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2954 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2955 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2959 /* >32-bits, result on stack, and FSR0 points to beginning.
2960 * Fix stack when done */
2962 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2964 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2965 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2967 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2972 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2973 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2974 if(STACK_MODEL_LARGE) {
2976 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2980 int areg = 0; /* matching argument register */
2982 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2983 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2986 /* its called from genReceive (probably) -- VR */
2987 /* I hope this code will not be called from somewhere else in the future!
2988 * We manually set the pseudo stack pointer in genReceive. - dw
2990 if(!GpsuedoStkPtr && _G.useWreg) {
2991 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2993 /* The last byte in the assignment is in W */
2994 if(areg <= GpsuedoStkPtr) {
2996 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2998 // debugf("receive from WREG\n", 0);
3000 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3003 _G.stack_lat = AOP_SIZE(oper)-1;
3008 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3009 // debugf("receive from STACK\n", 0);
3016 /*-----------------------------------------------------------------*/
3017 /* genIpush - generate code for pushing this gets a little complex */
3018 /*-----------------------------------------------------------------*/
3019 static void genIpush (iCode *ic)
3021 // int size, offset=0;
3024 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3027 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3029 /* send to stack as normal */
3030 addSet(&_G.sendSet,ic);
3031 // addSetHead(&_G.sendSet,ic);
3032 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3037 int size, offset = 0 ;
3041 /* if this is not a parm push : ie. it is spill push
3042 and spill push is always done on the local stack */
3043 if (!ic->parmPush) {
3045 /* and the item is spilt then do nothing */
3046 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3049 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3050 size = AOP_SIZE(IC_LEFT(ic));
3051 /* push it on the stack */
3053 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3058 pic16_emitcode("push","%s",l);
3063 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3067 /*-----------------------------------------------------------------*/
3068 /* genIpop - recover the registers: can happen only for spilling */
3069 /*-----------------------------------------------------------------*/
3070 static void genIpop (iCode *ic)
3073 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3078 /* if the temp was not pushed then */
3079 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3082 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3083 size = AOP_SIZE(IC_LEFT(ic));
3086 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3089 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3094 /*-----------------------------------------------------------------*/
3095 /* unsaverbank - restores the resgister bank from stack */
3096 /*-----------------------------------------------------------------*/
3097 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3099 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3105 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3107 if (options.useXstack) {
3109 r = getFreePtr(ic,&aop,FALSE);
3112 pic16_emitcode("mov","%s,_spx",r->name);
3113 pic16_emitcode("movx","a,@%s",r->name);
3114 pic16_emitcode("mov","psw,a");
3115 pic16_emitcode("dec","%s",r->name);
3118 pic16_emitcode ("pop","psw");
3121 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3122 if (options.useXstack) {
3123 pic16_emitcode("movx","a,@%s",r->name);
3124 //pic16_emitcode("mov","(%s+%d),a",
3125 // regspic16[i].base,8*bank+regspic16[i].offset);
3126 pic16_emitcode("dec","%s",r->name);
3129 pic16_emitcode("pop",""); //"(%s+%d)",
3130 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3133 if (options.useXstack) {
3135 pic16_emitcode("mov","_spx,%s",r->name);
3136 pic16_freeAsmop(NULL,aop,ic,TRUE);
3142 /*-----------------------------------------------------------------*/
3143 /* saverbank - saves an entire register bank on the stack */
3144 /*-----------------------------------------------------------------*/
3145 static void saverbank (int bank, iCode *ic, bool pushPsw)
3147 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3153 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3154 if (options.useXstack) {
3157 r = getFreePtr(ic,&aop,FALSE);
3158 pic16_emitcode("mov","%s,_spx",r->name);
3162 for (i = 0 ; i < pic16_nRegs ;i++) {
3163 if (options.useXstack) {
3164 pic16_emitcode("inc","%s",r->name);
3165 //pic16_emitcode("mov","a,(%s+%d)",
3166 // regspic16[i].base,8*bank+regspic16[i].offset);
3167 pic16_emitcode("movx","@%s,a",r->name);
3169 pic16_emitcode("push","");// "(%s+%d)",
3170 //regspic16[i].base,8*bank+regspic16[i].offset);
3174 if (options.useXstack) {
3175 pic16_emitcode("mov","a,psw");
3176 pic16_emitcode("movx","@%s,a",r->name);
3177 pic16_emitcode("inc","%s",r->name);
3178 pic16_emitcode("mov","_spx,%s",r->name);
3179 pic16_freeAsmop (NULL,aop,ic,TRUE);
3182 pic16_emitcode("push","psw");
3184 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3192 static int wparamCmp(void *p1, void *p2)
3194 return (!strcmp((char *)p1, (char *)p2));
3197 int inWparamList(char *s)
3199 return isinSetWith(wparamList, s, wparamCmp);
3203 /*-----------------------------------------------------------------*/
3204 /* genCall - generates a call statement */
3205 /*-----------------------------------------------------------------*/
3206 static void genCall (iCode *ic)
3216 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3217 /* if caller saves & we have not saved then */
3218 // if (!ic->regsSaved)
3219 // saveRegisters(ic);
3221 /* initialise stackParms for IPUSH pushes */
3222 // stackParms = psuedoStkPtr;
3223 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3224 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3225 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3228 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3231 /* if send set is not empty the assign */
3234 int psuedoStkPtr=-1;
3235 int firstTimeThruLoop = 1;
3238 /* reverse sendSet if function is not reentrant */
3239 if(!IFFUNC_ISREENT(ftype))
3240 _G.sendSet = reverseSet(_G.sendSet);
3242 /* First figure how many parameters are getting passed */
3246 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3250 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3251 size = AOP_SIZE(IC_LEFT(sic));
3255 /* pass the last byte through WREG */
3259 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3260 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3261 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3263 if(!firstTimeThruLoop) {
3264 /* If this is not the first time we've been through the loop
3265 * then we need to save the parameter in a temporary
3266 * register. The last byte of the last parameter is
3270 // --psuedoStkPtr; // sanity check
3274 firstTimeThruLoop=0;
3276 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3281 /* all arguments are passed via stack */
3285 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3286 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3287 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3289 // pushaop(AOP(IC_LEFT(sic)), size);
3290 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3297 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3301 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3302 pushw(); /* save last parameter to stack if functions has varargs */
3306 } else use_wreg = 0;
3308 _G.stackRegSet = _G.sendSet;
3313 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3317 /* if we need to assign a result value */
3318 if ((IS_ITEMP(IC_RESULT(ic))
3319 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3320 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3321 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3324 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3327 assignResultValue(IC_RESULT(ic), 1);
3329 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3330 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3332 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3335 if(!stackParms && ic->parmBytes) {
3336 stackParms = ic->parmBytes;
3339 stackParms -= use_wreg;
3342 if(stackParms == 1) {
3343 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3345 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3346 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3348 if(STACK_MODEL_LARGE) {
3350 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3355 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3358 /* adjust the stack for parameters if required */
3359 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3362 /* if register bank was saved then pop them */
3364 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3366 /* if we hade saved some registers then unsave them */
3367 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3368 unsaveRegisters (ic);
3374 /*-----------------------------------------------------------------*/
3375 /* genPcall - generates a call by pointer statement */
3376 /* new version, created from genCall - HJD */
3377 /*-----------------------------------------------------------------*/
3378 static void genPcall (iCode *ic)
3380 sym_link *ftype, *fntype;
3382 symbol *retlbl = newiTempLabel(NULL);
3383 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3387 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3388 fntype = operandType( IC_LEFT(ic) )->next;
3390 /* if send set is not empty the assign */
3393 int psuedoStkPtr=-1;
3395 /* reverse sendSet if function is not reentrant */
3396 if(!IFFUNC_ISREENT(fntype))
3397 _G.sendSet = reverseSet(_G.sendSet);
3401 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3404 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3405 size = AOP_SIZE(IC_LEFT(sic));
3408 /* all parameters are passed via stack, since WREG is clobbered
3409 * by the calling sequence */
3411 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3412 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3413 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3415 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3419 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3422 _G.stackRegSet = _G.sendSet;
3426 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3428 // push return address
3429 // push $ on return stack, then replace with retlbl
3431 /* Thanks to Thorsten Klose for pointing out that the following
3432 * snippet should be interrupt safe */
3433 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3434 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3436 pic16_emitpcodeNULLop(POC_PUSH);
3438 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3439 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3440 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3441 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3442 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3443 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3446 /* restore interrupt control register */
3447 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3448 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3450 /* make the call by writing the pointer into pc */
3451 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3452 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3454 // note: MOVFF to PCL not allowed
3455 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3456 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3459 /* return address is here: (X) */
3460 pic16_emitpLabelFORCE(retlbl->key);
3462 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3465 /* if we need assign a result value */
3466 if ((IS_ITEMP(IC_RESULT(ic))
3467 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3468 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3469 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3472 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3475 assignResultValue(IC_RESULT(ic), 1);
3477 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3478 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3480 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3483 // stackParms -= use_wreg;
3486 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3487 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3488 if(STACK_MODEL_LARGE) {
3490 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3495 /*-----------------------------------------------------------------*/
3496 /* resultRemat - result is rematerializable */
3497 /*-----------------------------------------------------------------*/
3498 static int resultRemat (iCode *ic)
3500 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3501 if (SKIP_IC(ic) || ic->op == IFX)
3504 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3505 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3506 if (sym->remat && !POINTER_SET(ic))
3513 #if defined(__BORLANDC__) || defined(_MSC_VER)
3514 #define STRCASECMP stricmp
3516 #define STRCASECMP strcasecmp
3520 /*-----------------------------------------------------------------*/
3521 /* inExcludeList - return 1 if the string is in exclude Reg list */
3522 /*-----------------------------------------------------------------*/
3523 static bool inExcludeList(char *s)
3525 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3528 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3529 if (options.excludeRegs[i] &&
3530 STRCASECMP(options.excludeRegs[i],"none") == 0)
3533 for ( i = 0 ; options.excludeRegs[i]; i++) {
3534 if (options.excludeRegs[i] &&
3535 STRCASECMP(s,options.excludeRegs[i]) == 0)
3542 /*-----------------------------------------------------------------*/
3543 /* genFunction - generated code for function entry */
3544 /*-----------------------------------------------------------------*/
3545 static void genFunction (iCode *ic)
3551 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3553 pic16_labelOffset += (max_key+4);
3558 ftype = operandType(IC_LEFT(ic));
3559 sym = OP_SYMBOL(IC_LEFT(ic));
3561 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3562 /* create an absolute section at the interrupt vector:
3563 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3568 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3570 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3571 sprintf(asymname, "ivec_%s", sym->name);
3573 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3575 /* when an interrupt is declared as naked, do not emit the special
3576 * wrapper segment at vector address. The user should take care for
3577 * this instead. -- VR */
3579 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3580 asym = newSymbol(asymname, 0);
3581 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3582 pic16_addpBlock( apb );
3584 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3585 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3586 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3587 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3588 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3590 /* mark the end of this tiny function */
3591 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3593 sprintf(asymname, "%s", sym->rname);
3599 abSym = Safe_calloc(1, sizeof(absSym));
3600 strcpy(abSym->name, asymname);
3602 switch( FUNC_INTNO(sym->type) ) {
3603 case 0: abSym->address = 0x000000; break;
3604 case 1: abSym->address = 0x000008; break;
3605 case 2: abSym->address = 0x000018; break;
3608 // fprintf(stderr, "no interrupt number is given\n");
3609 abSym->address = -1; break;
3612 /* relocate interrupt vectors if needed */
3613 if(abSym->address != -1)
3614 abSym->address += pic16_options.ivt_loc;
3616 addSet(&absSymSet, abSym);
3620 /* create the function header */
3621 pic16_emitcode(";","-----------------------------------------");
3622 pic16_emitcode(";"," function %s",sym->name);
3623 pic16_emitcode(";","-----------------------------------------");
3625 pic16_emitcode("","%s:",sym->rname);
3626 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3631 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3632 if(!strcmp(ab->name, sym->rname)) {
3633 pic16_pBlockConvert2Absolute(pb);
3639 if(IFFUNC_ISNAKED(ftype)) {
3640 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3644 /* if critical function then turn interrupts off */
3645 if (IFFUNC_ISCRITICAL(ftype)) {
3646 //pic16_emitcode("clr","ea");
3649 currFunc = sym; /* update the currFunc symbol */
3650 _G.fregsUsed = sym->regsUsed;
3651 _G.sregsAlloc = newBitVect(128);
3654 /* if this is an interrupt service routine then
3655 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3656 if (IFFUNC_ISISR(sym->type)) {
3657 _G.usefastretfie = 1; /* use shadow registers by default */
3659 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3660 if(!FUNC_ISSHADOWREGS(sym->type)) {
3661 /* do not save WREG,STATUS,BSR for high priority interrupts
3662 * because they are stored in the hardware shadow registers already */
3663 _G.usefastretfie = 0;
3664 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3665 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3666 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3669 /* these should really be optimized somehow, because not all
3670 * interrupt handlers modify them */
3671 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3672 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3673 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3674 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3676 // pic16_pBlockConvert2ISR(pb);
3679 /* emit code to setup stack frame if user enabled,
3680 * and function is not main() */
3682 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3683 if(strcmp(sym->name, "main")) {
3685 || !options.ommitFramePtr
3687 || IFFUNC_ARGS(sym->type)
3688 || FUNC_HASSTACKPARM(sym->etype)
3690 /* setup the stack frame */
3691 if(STACK_MODEL_LARGE)
3692 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3693 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3695 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3696 if(STACK_MODEL_LARGE)
3697 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3701 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3704 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3706 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3707 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3709 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3712 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3713 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3720 /* if callee-save to be used for this function
3721 * then save the registers being used in this function */
3722 // if (IFFUNC_CALLEESAVES(sym->type))
3726 /* if any registers used */
3727 if (sym->regsUsed) {
3728 /* save the registers used */
3729 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3730 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3731 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3732 if (bitVectBitValue(sym->regsUsed,i)) {
3733 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3736 if(!pic16_regWithIdx(i)->wasUsed) {
3737 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3738 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3739 pic16_regWithIdx(i)->wasUsed = 1;
3743 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3747 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3748 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3751 /*-----------------------------------------------------------------*/
3752 /* genEndFunction - generates epilogue for functions */
3753 /*-----------------------------------------------------------------*/
3754 static void genEndFunction (iCode *ic)
3756 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3760 if(IFFUNC_ISNAKED(sym->type)) {
3761 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3767 /* add code for ISCRITICAL */
3768 if(IFFUNC_ISCRITICAL(sym->type)) {
3769 /* if critical function, turn on interrupts */
3771 /* TODO: add code here -- VR */
3774 // sym->regsUsed = _G.fregsUsed;
3776 /* now we need to restore the registers */
3777 /* if any registers used */
3779 /* first restore registers that might be used for stack access */
3780 if(_G.sregsAllocSet) {
3783 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3784 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3785 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3789 if (sym->regsUsed) {
3792 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3793 /* restore registers used */
3794 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3795 for ( i = sym->regsUsed->size; i >= 0; i--) {
3796 if (bitVectBitValue(sym->regsUsed,i)) {
3797 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3801 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3806 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3808 if (sym->stack == 1) {
3809 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3810 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3812 // we have to add more than one...
3813 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3814 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3815 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3817 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3818 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3819 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3823 if(strcmp(sym->name, "main")) {
3825 || !options.ommitFramePtr
3827 || IFFUNC_ARGS(sym->type)
3828 || FUNC_HASSTACKPARM(sym->etype)
3830 /* restore stack frame */
3831 if(STACK_MODEL_LARGE)
3832 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3833 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3839 if (IFFUNC_ISISR(sym->type)) {
3840 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3841 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3842 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3843 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3845 if(!FUNC_ISSHADOWREGS(sym->type)) {
3846 /* do not restore interrupt vector for WREG,STATUS,BSR
3847 * for high priority interrupt, see genFunction */
3848 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3849 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3850 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3852 // _G.interruptvector = 0; /* sanity check */
3855 /* if debug then send end of function */
3856 /* if (options.debug && currFunc) */
3858 debugFile->writeEndFunction (currFunc, ic, 1);
3861 if(_G.usefastretfie)
3862 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3864 pic16_emitpcodeNULLop(POC_RETFIE);
3866 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3868 _G.usefastretfie = 0;
3872 if (IFFUNC_ISCRITICAL(sym->type)) {
3873 pic16_emitcode("setb","ea");
3876 /* if debug then send end of function */
3878 debugFile->writeEndFunction (currFunc, ic, 1);
3881 /* insert code to restore stack frame, if user enabled it
3882 * and function is not main() */
3885 pic16_emitpcodeNULLop(POC_RETURN);
3887 /* Mark the end of a function */
3888 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3892 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3894 unsigned long lit=1;
3899 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3900 if(AOP_TYPE(op) == AOP_LIT) {
3901 if(!IS_FLOAT(operandType( op ))) {
3902 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3905 unsigned long lit_int;
3909 /* take care if literal is a float */
3910 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3916 if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
3917 pic16_emitpcode(POC_CLRF, dest);
3919 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3920 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3923 if(dest->type == PO_WREG && (offset == 0)) {
3924 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3927 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3931 /*-----------------------------------------------------------------*/
3932 /* genRet - generate code for return statement */
3933 /*-----------------------------------------------------------------*/
3934 static void genRet (iCode *ic)
3940 /* if we have no return value then
3941 * just generate the "ret" */
3946 /* we have something to return then
3947 * move the return value into place */
3948 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3949 size = AOP_SIZE(IC_LEFT(ic));
3953 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3956 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3959 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3961 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3964 /* >32-bits, setup stack and FSR0 */
3966 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3967 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3969 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3971 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3976 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3977 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3979 if(STACK_MODEL_LARGE) {
3980 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3981 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3983 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3988 /* old code, left here for reference -- VR */
3992 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3994 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3995 pic16_emitpcomment("push %s",l);
3998 DEBUGpic16_emitcode(";", "%d", __LINE__);
3999 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4000 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4002 if (strcmp(fReturn[offset],l)) {
4003 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4004 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4005 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4007 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4011 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4021 if (strcmp(fReturn[pushed],"a"))
4022 pic16_emitcode("pop",fReturn[pushed]);
4024 pic16_emitcode("pop","acc");
4030 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4033 /* generate a jump to the return label
4034 * if the next is not the return statement */
4035 if (!(ic->next && ic->next->op == LABEL
4036 && IC_LABEL(ic->next) == returnLabel)) {
4038 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4039 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4043 /*-----------------------------------------------------------------*/
4044 /* genLabel - generates a label */
4045 /*-----------------------------------------------------------------*/
4046 static void genLabel (iCode *ic)
4050 /* special case never generate */
4051 if (IC_LABEL(ic) == entryLabel)
4054 pic16_emitpLabel(IC_LABEL(ic)->key);
4055 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4058 /*-----------------------------------------------------------------*/
4059 /* genGoto - generates a goto */
4060 /*-----------------------------------------------------------------*/
4062 static void genGoto (iCode *ic)
4065 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4066 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4070 /*-----------------------------------------------------------------*/
4071 /* genMultbits :- multiplication of bits */
4072 /*-----------------------------------------------------------------*/
4073 static void genMultbits (operand *left,
4079 if(!pic16_sameRegs(AOP(result),AOP(right)))
4080 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4082 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4083 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4084 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4089 /*-----------------------------------------------------------------*/
4090 /* genMultOneByte : 8 bit multiplication & division */
4091 /*-----------------------------------------------------------------*/
4092 static void genMultOneByte (operand *left,
4098 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4099 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4101 /* (if two literals, the value is computed before) */
4102 /* if one literal, literal on the right */
4103 if (AOP_TYPE(left) == AOP_LIT){
4109 /* size is already checked in genMult == 1 */
4110 // size = AOP_SIZE(result);
4112 if (AOP_TYPE(right) == AOP_LIT){
4113 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4114 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4115 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4116 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4118 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4119 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4120 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4121 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4124 pic16_genMult8X8_8 (left, right,result);
4127 /*-----------------------------------------------------------------*/
4128 /* genMultOneWord : 16 bit multiplication */
4129 /*-----------------------------------------------------------------*/
4130 static void genMultOneWord (operand *left,
4135 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4136 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4138 /* (if two literals, the value is computed before)
4139 * if one literal, literal on the right */
4140 if (AOP_TYPE(left) == AOP_LIT){
4146 /* size is checked already == 2 */
4147 // size = AOP_SIZE(result);
4149 if (AOP_TYPE(right) == AOP_LIT) {
4150 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4151 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4152 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4153 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4155 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4156 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4157 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4158 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4161 pic16_genMult16X16_16(left, right,result);
4164 /*-----------------------------------------------------------------*/
4165 /* genMultOneLong : 32 bit multiplication */
4166 /*-----------------------------------------------------------------*/
4167 static void genMultOneLong (operand *left,
4172 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4173 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4175 /* (if two literals, the value is computed before)
4176 * if one literal, literal on the right */
4177 if (AOP_TYPE(left) == AOP_LIT){
4183 /* size is checked already == 4 */
4184 // size = AOP_SIZE(result);
4186 if (AOP_TYPE(right) == AOP_LIT) {
4187 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4188 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4189 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4190 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4192 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4193 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4194 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4195 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4198 pic16_genMult32X32_32(left, right,result);
4203 /*-----------------------------------------------------------------*/
4204 /* genMult - generates code for multiplication */
4205 /*-----------------------------------------------------------------*/
4206 static void genMult (iCode *ic)
4208 operand *left = IC_LEFT(ic);
4209 operand *right = IC_RIGHT(ic);
4210 operand *result= IC_RESULT(ic);
4213 /* assign the amsops */
4214 pic16_aopOp (left,ic,FALSE);
4215 pic16_aopOp (right,ic,FALSE);
4216 pic16_aopOp (result,ic,TRUE);
4218 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4220 /* special cases first *
4222 if (AOP_TYPE(left) == AOP_CRY
4223 && AOP_TYPE(right)== AOP_CRY) {
4224 genMultbits(left,right,result);
4228 /* if both are of size == 1 */
4229 if(AOP_SIZE(left) == 1
4230 && AOP_SIZE(right) == 1) {
4231 genMultOneByte(left,right,result);
4235 /* if both are of size == 2 */
4236 if(AOP_SIZE(left) == 2
4237 && AOP_SIZE(right) == 2) {
4238 genMultOneWord(left, right, result);
4242 /* if both are of size == 4 */
4243 if(AOP_SIZE(left) == 4
4244 && AOP_SIZE(right) == 4) {
4245 genMultOneLong(left, right, result);
4249 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4252 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4253 /* should have been converted to function call */
4257 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4258 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4259 pic16_freeAsmop(result,NULL,ic,TRUE);
4262 /*-----------------------------------------------------------------*/
4263 /* genDivbits :- division of bits */
4264 /*-----------------------------------------------------------------*/
4265 static void genDivbits (operand *left,
4272 /* the result must be bit */
4273 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4274 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4278 pic16_emitcode("div","ab");
4279 pic16_emitcode("rrc","a");
4280 pic16_aopPut(AOP(result),"c",0);
4283 /*-----------------------------------------------------------------*/
4284 /* genDivOneByte : 8 bit division */
4285 /*-----------------------------------------------------------------*/
4286 static void genDivOneByte (operand *left,
4290 sym_link *opetype = operandType(result);
4295 /* result = divident / divisor
4296 * - divident may be a register or a literal,
4297 * - divisor may be a register or a literal,
4298 * so there are 3 cases (literal / literal is optimized
4299 * by the front-end) to handle.
4300 * In addition we must handle signed and unsigned, which
4301 * result in 6 final different cases -- VR */
4305 size = AOP_SIZE(result) - 1;
4307 /* signed or unsigned */
4308 if (SPEC_USIGN(opetype)) {
4309 pCodeOp *pct1, /* count */
4312 symbol *label1, *label2, *label3;;
4315 /* unsigned is easy */
4317 pct1 = pic16_popGetTempReg(1);
4318 pct2 = pic16_popGetTempReg(1);
4319 pct3 = pic16_popGetTempReg(1);
4321 label1 = newiTempLabel(NULL);
4322 label2 = newiTempLabel(NULL);
4323 label3 = newiTempLabel(NULL);
4325 /* the following algorithm is extracted from divuint.c */
4327 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4328 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4330 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4332 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4334 pic16_emitpLabel(label1->key);
4337 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4341 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4345 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4347 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4348 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4350 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4351 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4352 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4354 pic16_emitpLabel( label3->key );
4355 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4356 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4360 pic16_emitpLabel(label2->key);
4361 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4362 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4363 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4365 /* result is in wreg */
4366 if(AOP_TYPE(result) != AOP_ACC)
4367 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4369 pic16_popReleaseTempReg( pct3, 1);
4370 pic16_popReleaseTempReg( pct2, 1);
4371 pic16_popReleaseTempReg( pct1, 1);
4376 /* signed is a little bit more difficult */
4378 /* save the signs of the operands */
4379 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4381 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4382 pic16_emitcode("push","acc"); /* save it on the stack */
4384 /* now sign adjust for both left & right */
4385 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4387 lbl = newiTempLabel(NULL);
4388 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4389 pic16_emitcode("cpl","a");
4390 pic16_emitcode("inc","a");
4391 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4392 pic16_emitcode("mov","b,a");
4394 /* sign adjust left side */
4395 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4398 lbl = newiTempLabel(NULL);
4399 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4400 pic16_emitcode("cpl","a");
4401 pic16_emitcode("inc","a");
4402 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4404 /* now the division */
4405 pic16_emitcode("div","ab");
4406 /* we are interested in the lower order
4408 pic16_emitcode("mov","b,a");
4409 lbl = newiTempLabel(NULL);
4410 pic16_emitcode("pop","acc");
4411 /* if there was an over flow we don't
4412 adjust the sign of the result */
4413 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4414 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4416 pic16_emitcode("clr","a");
4417 pic16_emitcode("subb","a,b");
4418 pic16_emitcode("mov","b,a");
4419 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4421 /* now we are done */
4422 pic16_aopPut(AOP(result),"b",0);
4424 pic16_emitcode("mov","c,b.7");
4425 pic16_emitcode("subb","a,acc");
4428 pic16_aopPut(AOP(result),"a",offset++);
4432 /*-----------------------------------------------------------------*/
4433 /* genDiv - generates code for division */
4434 /*-----------------------------------------------------------------*/
4435 static void genDiv (iCode *ic)
4437 operand *left = IC_LEFT(ic);
4438 operand *right = IC_RIGHT(ic);
4439 operand *result= IC_RESULT(ic);
4442 /* Division is a very lengthy algorithm, so it is better
4443 * to call support routines than inlining algorithm.
4444 * Division functions written here just in case someone
4445 * wants to inline and not use the support libraries -- VR */
4449 /* assign the amsops */
4450 pic16_aopOp (left,ic,FALSE);
4451 pic16_aopOp (right,ic,FALSE);
4452 pic16_aopOp (result,ic,TRUE);
4454 /* special cases first */
4456 if (AOP_TYPE(left) == AOP_CRY &&
4457 AOP_TYPE(right)== AOP_CRY) {
4458 genDivbits(left,right,result);
4462 /* if both are of size == 1 */
4463 if (AOP_SIZE(left) == 1 &&
4464 AOP_SIZE(right) == 1 ) {
4465 genDivOneByte(left,right,result);
4469 /* should have been converted to function call */
4472 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4473 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4474 pic16_freeAsmop(result,NULL,ic,TRUE);
4477 /*-----------------------------------------------------------------*/
4478 /* genModbits :- modulus of bits */
4479 /*-----------------------------------------------------------------*/
4480 static void genModbits (operand *left,
4488 werror(W_POSSBUG2, __FILE__, __LINE__);
4489 /* the result must be bit */
4490 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4491 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4495 pic16_emitcode("div","ab");
4496 pic16_emitcode("mov","a,b");
4497 pic16_emitcode("rrc","a");
4498 pic16_aopPut(AOP(result),"c",0);
4501 /*-----------------------------------------------------------------*/
4502 /* genModOneByte : 8 bit modulus */
4503 /*-----------------------------------------------------------------*/
4504 static void genModOneByte (operand *left,
4508 sym_link *opetype = operandType(result);
4513 werror(W_POSSBUG2, __FILE__, __LINE__);
4515 /* signed or unsigned */
4516 if (SPEC_USIGN(opetype)) {
4517 /* unsigned is easy */
4518 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4519 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4521 pic16_emitcode("div","ab");
4522 pic16_aopPut(AOP(result),"b",0);
4526 /* signed is a little bit more difficult */
4528 /* save the signs of the operands */
4529 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4532 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4533 pic16_emitcode("push","acc"); /* save it on the stack */
4535 /* now sign adjust for both left & right */
4536 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4539 lbl = newiTempLabel(NULL);
4540 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4541 pic16_emitcode("cpl","a");
4542 pic16_emitcode("inc","a");
4543 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4544 pic16_emitcode("mov","b,a");
4546 /* sign adjust left side */
4547 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4550 lbl = newiTempLabel(NULL);
4551 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4552 pic16_emitcode("cpl","a");
4553 pic16_emitcode("inc","a");
4554 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4556 /* now the multiplication */
4557 pic16_emitcode("div","ab");
4558 /* we are interested in the lower order
4560 lbl = newiTempLabel(NULL);
4561 pic16_emitcode("pop","acc");
4562 /* if there was an over flow we don't
4563 adjust the sign of the result */
4564 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4565 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4567 pic16_emitcode("clr","a");
4568 pic16_emitcode("subb","a,b");
4569 pic16_emitcode("mov","b,a");
4570 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4572 /* now we are done */
4573 pic16_aopPut(AOP(result),"b",0);
4577 /*-----------------------------------------------------------------*/
4578 /* genMod - generates code for division */
4579 /*-----------------------------------------------------------------*/
4580 static void genMod (iCode *ic)
4582 operand *left = IC_LEFT(ic);
4583 operand *right = IC_RIGHT(ic);
4584 operand *result= IC_RESULT(ic);
4588 /* assign the amsops */
4589 pic16_aopOp (left,ic,FALSE);
4590 pic16_aopOp (right,ic,FALSE);
4591 pic16_aopOp (result,ic,TRUE);
4593 /* special cases first */
4595 if (AOP_TYPE(left) == AOP_CRY &&
4596 AOP_TYPE(right)== AOP_CRY) {
4597 genModbits(left,right,result);
4601 /* if both are of size == 1 */
4602 if (AOP_SIZE(left) == 1 &&
4603 AOP_SIZE(right) == 1 ) {
4604 genModOneByte(left,right,result);
4608 /* should have been converted to function call */
4612 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4613 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4614 pic16_freeAsmop(result,NULL,ic,TRUE);
4617 /*-----------------------------------------------------------------*/
4618 /* genIfxJump :- will create a jump depending on the ifx */
4619 /*-----------------------------------------------------------------*/
4621 note: May need to add parameter to indicate when a variable is in bit space.
4623 static void genIfxJump (iCode *ic, char *jval)
4627 /* if true label then we jump if condition
4629 if ( IC_TRUE(ic) ) {
4631 if(strcmp(jval,"a") == 0)
4633 else if (strcmp(jval,"c") == 0)
4636 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4637 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4640 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4641 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4645 /* false label is present */
4646 if(strcmp(jval,"a") == 0)
4648 else if (strcmp(jval,"c") == 0)
4651 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4652 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4655 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4656 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4661 /* mark the icode as generated */
4665 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4669 /* if true label then we jump if condition
4671 if ( IC_TRUE(ic) ) {
4672 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4673 pic16_emitpcode(POC_BTFSC, jop);
4675 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4676 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4679 /* false label is present */
4680 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4681 pic16_emitpcode(POC_BTFSS, jop);
4683 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4684 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4688 /* mark the icode as generated */
4695 /*-----------------------------------------------------------------*/
4697 /*-----------------------------------------------------------------*/
4698 static void genSkip(iCode *ifx,int status_bit)
4700 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4704 if ( IC_TRUE(ifx) ) {
4705 switch(status_bit) {
4720 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4721 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4725 switch(status_bit) {
4739 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4740 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4747 /*-----------------------------------------------------------------*/
4749 /*-----------------------------------------------------------------*/
4750 static void genSkipc(resolvedIfx *rifx)
4752 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4762 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4763 rifx->generated = 1;
4766 #if !(USE_SIMPLE_GENCMP)
4767 /*-----------------------------------------------------------------*/
4769 /*-----------------------------------------------------------------*/
4770 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4772 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4777 if( (rifx->condition ^ invert_condition) & 1)
4782 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4783 rifx->generated = 1;
4788 /*-----------------------------------------------------------------*/
4790 /*-----------------------------------------------------------------*/
4791 static void genSkipz(iCode *ifx, int condition)
4802 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4804 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4807 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4809 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4814 #if !(USE_SIMPLE_GENCMP)
4815 /*-----------------------------------------------------------------*/
4817 /*-----------------------------------------------------------------*/
4818 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4824 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4826 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4829 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4830 rifx->generated = 1;
4835 /*-----------------------------------------------------------------*/
4836 /* genChkZeroes :- greater or less than comparison */
4837 /* For each byte in a literal that is zero, inclusive or the */
4838 /* the corresponding byte in the operand with W */
4839 /* returns true if any of the bytes are zero */
4840 /*-----------------------------------------------------------------*/
4841 static int genChkZeroes(operand *op, int lit, int size)
4848 i = (lit >> (size*8)) & 0xff;
4852 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4854 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4864 /*-----------------------------------------------------------------*/
4865 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4866 /* aop (if it's NOT a literal) or from lit (if */
4867 /* aop is a literal) */
4868 /*-----------------------------------------------------------------*/
4869 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4870 if (aop->type == AOP_LIT) {
4871 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4873 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4877 /*-----------------------------------------------------------------*/
4878 /* genCmp :- greater or less than comparison */
4879 /*-----------------------------------------------------------------*/
4881 #if USE_SIMPLE_GENCMP /* { */
4883 /* genCmp performs a left < right comparison, stores
4884 * the outcome in result (if != NULL) and generates
4885 * control flow code for the ifx (if != NULL).
4887 * This version leaves in sequences like
4888 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4889 * which should be optmized by the peephole
4890 * optimizer - RN 2005-01-01 */
4891 static void genCmp (operand *left,operand *right,
4892 operand *result, iCode *ifx, int sign)
4905 assert (left && right);
4906 assert (AOP_SIZE(left) == AOP_SIZE(right));
4908 size = AOP_SIZE(right) - 1;
4909 mask = (0x100UL << (size*8)) - 1;
4910 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4915 resolveIfx (&rIfx, ifx);
4917 /* handle for special cases */
4918 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4921 /**********************************************************************
4922 * handle bits - bit compares are promoted to int compares seemingly! *
4923 **********************************************************************/
4925 // THIS IS COMPLETELY UNTESTED!
4926 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4927 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4928 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4929 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4932 // 1 < {0,1} is false --> clear C by skipping the next instruction
4933 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4934 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4935 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4936 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4937 emitCLRC; // only skipped for left=0 && right=1
4939 goto correct_result_in_carry;
4943 /*************************************************
4944 * make sure that left is register (or the like) *
4945 *************************************************/
4946 if (!isAOP_REGlike(left)) {
4947 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4948 assert (isAOP_LIT(left));
4949 assert (isAOP_REGlike(right));
4950 // swap left and right
4951 // left < right <==> right > left <==> (right >= left + 1)
4952 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4954 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4955 // MAXVALUE < right? always false
4956 if (performedLt) emitCLRC; else emitSETC;
4957 goto correct_result_in_carry;
4960 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4961 // that's why we handled it above.
4968 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4969 } else if (isAOP_LIT(right)) {
4970 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4973 assert (isAOP_REGlike(left)); // left must be register or the like
4974 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4976 /*************************************************
4977 * special cases go here *
4978 *************************************************/
4980 if (isAOP_LIT(right)) {
4982 // unsigned comparison to a literal
4983 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4985 // unsigned left < 0? always false
4986 if (performedLt) emitCLRC; else emitSETC;
4987 goto correct_result_in_carry;
4990 // signed comparison to a literal
4991 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4992 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4993 // signed left < 0x80000000? always false
4994 if (performedLt) emitCLRC; else emitSETC;
4995 goto correct_result_in_carry;
4996 } else if (lit == 0) {
4997 // compare left < 0; set CARRY if SIGNBIT(left) is set
4998 if (performedLt) emitSETC; else emitCLRC;
4999 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5000 if (performedLt) emitCLRC; else emitSETC;
5001 goto correct_result_in_carry;
5004 } // right is literal
5006 /*************************************************
5007 * perform a general case comparison *
5008 * make sure we get CARRY==1 <==> left >= right *
5009 *************************************************/
5010 // compare most significant bytes
5011 //DEBUGpc ("comparing bytes at offset %d", size);
5013 // unsigned comparison
5014 mov2w_regOrLit (AOP(right), lit, size);
5015 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5017 // signed comparison
5018 // (add 2^n to both operands then perform an unsigned comparison)
5019 if (isAOP_LIT(right)) {
5020 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5021 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5023 if (litbyte == 0x80) {
5024 // left >= 0x80 -- always true, but more bytes to come
5025 pic16_mov2w (AOP(left), size);
5026 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5029 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5030 pic16_mov2w (AOP(left), size);
5031 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5032 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5035 /* using PRODL as a temporary register here */
5036 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5037 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5038 pic16_mov2w (AOP(left), size);
5039 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5040 pic16_emitpcode (POC_MOVWF, pctemp);
5041 pic16_mov2w (AOP(right), size);
5042 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5043 pic16_emitpcode (POC_SUBFW, pctemp);
5044 //pic16_popReleaseTempReg(pctemp, 1);
5048 // compare remaining bytes (treat as unsigned case from above)
5049 templbl = newiTempLabel ( NULL );
5052 //DEBUGpc ("comparing bytes at offset %d", offs);
5053 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5054 mov2w_regOrLit (AOP(right), lit, offs);
5055 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5057 pic16_emitpLabel (templbl->key);
5058 goto result_in_carry;
5062 /****************************************************
5063 * now CARRY contains the result of the comparison: *
5064 * SUBWF sets CARRY iff *
5065 * F-W >= 0 <==> F >= W <==> !(F < W) *
5066 * (F=left, W=right) *
5067 ****************************************************/
5070 if (result && AOP_TYPE(result) != AOP_CRY) {
5071 // value will be stored
5074 // value wil only be used in the following genSkipc()
5075 rIfx.condition ^= 1;
5079 correct_result_in_carry:
5081 // assign result to variable (if neccessary)
5082 if (result && AOP_TYPE(result) != AOP_CRY) {
5083 //DEBUGpc ("assign result");
5084 size = AOP_SIZE(result);
5086 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5088 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5091 // perform conditional jump
5093 //DEBUGpc ("generate control flow");
5102 static void genCmp (operand *left,operand *right,
5103 operand *result, iCode *ifx, int sign)
5105 int size; //, offset = 0 ;
5106 unsigned long lit = 0L,i = 0;
5107 resolvedIfx rFalseIfx;
5108 // resolvedIfx rTrueIfx;
5110 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5113 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5114 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5120 resolveIfx(&rFalseIfx,ifx);
5121 truelbl = newiTempLabel(NULL);
5122 size = max(AOP_SIZE(left),AOP_SIZE(right));
5124 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5128 /* if literal is on the right then swap with left */
5129 if ((AOP_TYPE(right) == AOP_LIT)) {
5130 operand *tmp = right ;
5131 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5132 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5135 lit = (lit - 1) & mask;
5138 rFalseIfx.condition ^= 1;
5141 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5142 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5146 //if(IC_TRUE(ifx) == NULL)
5147 /* if left & right are bit variables */
5148 if (AOP_TYPE(left) == AOP_CRY &&
5149 AOP_TYPE(right) == AOP_CRY ) {
5150 assert (0 && "bit variables used in genCmp");
5151 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5152 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5154 /* subtract right from left if at the
5155 end the carry flag is set then we know that
5156 left is greater than right */
5158 symbol *lbl = newiTempLabel(NULL);
5161 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5162 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5166 if(AOP_TYPE(right) == AOP_LIT) {
5168 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5170 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5177 genSkipCond(&rFalseIfx,left,size-1,7);
5179 /* no need to compare to 0...*/
5180 /* NOTE: this is a de-generate compare that most certainly
5181 * creates some dead code. */
5182 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5184 if(ifx) ifx->generated = 1;
5191 //i = (lit >> (size*8)) & 0xff;
5192 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5194 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5196 i = ((0-lit) & 0xff);
5199 /* lit is 0x7f, all signed chars are less than
5200 * this except for 0x7f itself */
5201 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5202 genSkipz2(&rFalseIfx,0);
5204 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5205 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5206 genSkipc(&rFalseIfx);
5211 genSkipz2(&rFalseIfx,1);
5213 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5214 genSkipc(&rFalseIfx);
5218 if(ifx) ifx->generated = 1;
5222 /* chars are out of the way. now do ints and longs */
5225 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5232 genSkipCond(&rFalseIfx,left,size,7);
5233 if(ifx) ifx->generated = 1;
5238 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5240 //rFalseIfx.condition ^= 1;
5241 //genSkipCond(&rFalseIfx,left,size,7);
5242 //rFalseIfx.condition ^= 1;
5244 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5245 if(rFalseIfx.condition)
5246 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5248 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5250 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5251 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5252 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5255 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5257 if(rFalseIfx.condition) {
5259 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5265 genSkipc(&rFalseIfx);
5266 pic16_emitpLabel(truelbl->key);
5267 if(ifx) ifx->generated = 1;
5274 if( (lit & 0xff) == 0) {
5275 /* lower byte is zero */
5276 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5277 i = ((lit >> 8) & 0xff) ^0x80;
5278 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5279 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5280 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5281 genSkipc(&rFalseIfx);
5284 if(ifx) ifx->generated = 1;
5289 /* Special cases for signed longs */
5290 if( (lit & 0xffffff) == 0) {
5291 /* lower byte is zero */
5292 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5293 i = ((lit >> 8*3) & 0xff) ^0x80;
5294 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5295 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5296 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5297 genSkipc(&rFalseIfx);
5300 if(ifx) ifx->generated = 1;
5308 if(lit & (0x80 << (size*8))) {
5309 /* lit is negative */
5310 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5312 //genSkipCond(&rFalseIfx,left,size,7);
5314 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5316 if(rFalseIfx.condition)
5317 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5319 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5323 /* lit is positive */
5324 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5325 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5326 if(rFalseIfx.condition)
5327 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5329 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5334 This works, but is only good for ints.
5335 It also requires a "known zero" register.
5336 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5337 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5338 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5339 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5340 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5341 genSkipc(&rFalseIfx);
5343 pic16_emitpLabel(truelbl->key);
5344 if(ifx) ifx->generated = 1;
5348 /* There are no more special cases, so perform a general compare */
5350 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5351 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5355 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5357 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5359 //rFalseIfx.condition ^= 1;
5360 genSkipc(&rFalseIfx);
5362 pic16_emitpLabel(truelbl->key);
5364 if(ifx) ifx->generated = 1;
5371 /* sign is out of the way. So now do an unsigned compare */
5372 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5375 /* General case - compare to an unsigned literal on the right.*/
5377 i = (lit >> (size*8)) & 0xff;
5378 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5379 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5381 i = (lit >> (size*8)) & 0xff;
5384 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5386 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5388 /* this byte of the lit is zero,
5389 *if it's not the last then OR in the variable */
5391 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5396 pic16_emitpLabel(lbl->key);
5397 // pic16_emitpLabel(truelbl->key);
5398 //if(emitFinalCheck)
5399 genSkipc(&rFalseIfx);
5401 pic16_emitpLabel(truelbl->key);
5403 if(ifx) ifx->generated = 1;
5410 if(AOP_TYPE(left) == AOP_LIT) {
5411 //symbol *lbl = newiTempLabel(NULL);
5413 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5416 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5419 if((lit == 0) && (sign == 0)){
5422 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5424 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5426 genSkipz2(&rFalseIfx,0);
5427 if(ifx) ifx->generated = 1;
5434 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5435 /* degenerate compare can never be true */
5436 if(rFalseIfx.condition == 0)
5437 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5439 if(ifx) ifx->generated = 1;
5444 /* signed comparisons to a literal byte */
5446 int lp1 = (lit+1) & 0xff;
5448 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5451 rFalseIfx.condition ^= 1;
5452 genSkipCond(&rFalseIfx,right,0,7);
5455 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5456 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5457 genSkipz2(&rFalseIfx,1);
5460 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5461 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5462 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5463 rFalseIfx.condition ^= 1;
5464 genSkipc(&rFalseIfx);
5468 /* unsigned comparisons to a literal byte */
5470 switch(lit & 0xff ) {
5472 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5473 genSkipz2(&rFalseIfx,0);
5476 rFalseIfx.condition ^= 1;
5477 genSkipCond(&rFalseIfx,right,0,7);
5481 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5482 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5483 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5484 rFalseIfx.condition ^= 1;
5485 if (AOP_TYPE(result) == AOP_CRY)
5486 genSkipc(&rFalseIfx);
5488 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5489 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5495 if(ifx) ifx->generated = 1;
5496 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5502 /* Size is greater than 1 */
5510 /* this means lit = 0xffffffff, or -1 */
5513 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5514 rFalseIfx.condition ^= 1;
5515 genSkipCond(&rFalseIfx,right,size,7);
5516 if(ifx) ifx->generated = 1;
5518 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5527 if(rFalseIfx.condition) {
5528 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5529 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5532 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5534 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5538 if(rFalseIfx.condition) {
5539 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5540 pic16_emitpLabel(truelbl->key);
5542 rFalseIfx.condition ^= 1;
5543 genSkipCond(&rFalseIfx,right,s,7);
5546 if(ifx) ifx->generated = 1;
5548 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5554 if((size == 1) && (0 == (lp1&0xff))) {
5555 /* lower byte of signed word is zero */
5556 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5557 i = ((lp1 >> 8) & 0xff) ^0x80;
5558 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5559 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5560 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5562 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5564 if(ifx) ifx->generated = 1;
5567 rFalseIfx.condition ^= 1;
5568 genSkipc(&rFalseIfx);
5569 if(ifx) ifx->generated = 1;
5575 if(lit & (0x80 << (size*8))) {
5576 /* Lit is less than zero */
5577 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5578 //rFalseIfx.condition ^= 1;
5579 //genSkipCond(&rFalseIfx,left,size,7);
5580 //rFalseIfx.condition ^= 1;
5581 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5582 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5584 if(rFalseIfx.condition)
5585 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5587 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5591 /* Lit is greater than or equal to zero */
5592 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5593 //rFalseIfx.condition ^= 1;
5594 //genSkipCond(&rFalseIfx,right,size,7);
5595 //rFalseIfx.condition ^= 1;
5597 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5598 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5600 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5601 if(rFalseIfx.condition)
5602 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5604 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5608 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5609 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5613 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5615 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5617 rFalseIfx.condition ^= 1;
5618 //rFalseIfx.condition = 1;
5619 genSkipc(&rFalseIfx);
5621 pic16_emitpLabel(truelbl->key);
5623 if(ifx) ifx->generated = 1;
5626 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5633 /* compare word or long to an unsigned literal on the right.*/
5638 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5641 break; /* handled above */
5644 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5646 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5647 genSkipz2(&rFalseIfx,0);
5651 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5653 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5656 if(rFalseIfx.condition)
5657 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5659 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5662 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5663 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5665 rFalseIfx.condition ^= 1;
5666 genSkipc(&rFalseIfx);
5669 pic16_emitpLabel(truelbl->key);
5671 if(ifx) ifx->generated = 1;
5673 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5681 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5682 i = (lit >> (size*8)) & 0xff;
5684 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5685 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5688 i = (lit >> (size*8)) & 0xff;
5691 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5693 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5695 /* this byte of the lit is zero,
5696 * if it's not the last then OR in the variable */
5698 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5703 pic16_emitpLabel(lbl->key);
5705 rFalseIfx.condition ^= 1;
5707 genSkipc(&rFalseIfx);
5711 pic16_emitpLabel(truelbl->key);
5712 if(ifx) ifx->generated = 1;
5714 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5720 /* Compare two variables */
5722 DEBUGpic16_emitcode(";sign","%d",sign);
5726 /* Sigh. thus sucks... */
5730 pctemp = pic16_popGetTempReg(1);
5731 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5732 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5733 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5734 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5735 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5736 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5737 pic16_popReleaseTempReg(pctemp, 1);
5739 /* Signed char comparison */
5740 /* Special thanks to Nikolai Golovchenko for this snippet */
5741 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5742 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5743 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5744 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5745 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5746 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5748 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5749 genSkipc(&rFalseIfx);
5751 if(ifx) ifx->generated = 1;
5753 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5761 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5762 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5766 /* The rest of the bytes of a multi-byte compare */
5770 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5773 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5774 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5779 pic16_emitpLabel(lbl->key);
5781 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5782 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5783 (AOP_TYPE(result) == AOP_REG)) {
5784 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5785 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5787 genSkipc(&rFalseIfx);
5789 //genSkipc(&rFalseIfx);
5790 if(ifx) ifx->generated = 1;
5793 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5801 if ((AOP_TYPE(result) != AOP_CRY)
5802 && AOP_SIZE(result)) {
5803 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5805 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5807 pic16_outBitC(result);
5809 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5810 /* if the result is used in the next
5811 ifx conditional branch then generate
5812 code a little differently */
5814 genIfxJump (ifx,"c");
5816 pic16_outBitC(result);
5817 /* leave the result in acc */
5822 #elif 0 /* VR version of genCmp() */ /* } else { */
5824 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5825 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5826 operand *result, int offset, int invert_op)
5830 /* check condition, > or < ?? */
5831 if(rIfx->condition != 0)invert_op ^= 1;
5833 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5835 if(!ifx)invert_op ^= 1;
5837 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5838 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5841 if(!invert_op)return POC_CPFSGT;
5842 else return POC_CPFSLT;
5845 static int compareAopfirstpass=1;
5847 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5848 operand *oper, int offset, operand *result,
5849 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5855 /* invert if there is a result to be loaded, in order to fit,
5856 * SETC/CLRC sequence */
5857 if(AOP_SIZE(result))invert_op ^= 1;
5859 // if(sign && !offset)invert_op ^= 1;
5861 // if(sign)invert_op ^= 1;
5863 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5865 if(AOP_SIZE(result) && compareAopfirstpass) {
5868 pic16_emitpcode(POC_SETF, pcop2);
5873 pic16_emitpcode(POC_CLRF, pcop2);
5879 compareAopfirstpass = 0;
5881 /* there is a bug when comparing operands with size > 1,
5882 * because higher bytes can be equal and test should be performed
5883 * to the next lower byte, current algorithm, considers operands
5884 * inequal in these cases! -- VR 20041107 */
5888 pic16_emitpcode(op, pcop);
5890 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5893 if((!sign || !offset) && AOP_SIZE(result)) {
5896 pic16_emitpcode(POC_CLRF, pcop2);
5901 pic16_emitpcode(POC_SETF, pcop2);
5906 /* don't emit final branch (offset == 0) */
5910 pic16_emitpcode(POC_RRCF, pcop2);
5912 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5915 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5916 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5917 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5919 truelbl = newiTempLabel( NULL );
5920 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5921 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5922 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5924 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5925 pic16_emitpLabel(truelbl->key);
5927 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5932 static void genCmp (operand *left, operand *right,
5933 operand *result, iCode *ifx, int sign)
5937 resolvedIfx rFalseIfx;
5938 symbol *falselbl, *tlbl;
5942 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5944 resolveIfx(&rFalseIfx, ifx);
5945 size = max(AOP_SIZE(left), AOP_SIZE(right));
5947 /* if left & right are bit variables */
5948 if(AOP_TYPE(left) == AOP_CRY
5949 && AOP_TYPE(right) == AOP_CRY ) {
5951 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5952 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5954 werror(W_POSSBUG2, __FILE__, __LINE__);
5958 /* if literal is on the right then swap with left */
5959 if((AOP_TYPE(right) == AOP_LIT)) {
5960 operand *tmp = right ;
5961 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5963 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5965 // lit = (lit - 1) & mask;
5968 rFalseIfx.condition ^= 1; /* reverse compare */
5970 if ((AOP_TYPE(left) == AOP_LIT)) {
5971 /* float compares are handled by support functions */
5972 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5975 /* actual comparing algorithm */
5976 // size = AOP_SIZE( right );
5978 falselbl = newiTempLabel( NULL );
5979 if(AOP_TYPE(left) == AOP_LIT) {
5980 /* compare to literal */
5981 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5984 pCodeOp *pct, *pct2;
5987 /* signed compare */
5988 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5990 /* using PRODL:PRODH as a temporary register here */
5991 pct = pic16_popCopyReg(&pic16_pc_prodl);
5992 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5993 tlbl = newiTempLabel( NULL );
5995 /* first compare signs:
5996 * a. if both are positive, compare just like unsigned
5997 * b. if both are negative, invert cmpop, compare just like unsigned
5998 * c. if different signs, determine the result directly */
6004 tlbl1 = newiTempLabel( NULL );
6005 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6009 /* literal is zero or positive:
6010 * a. if carry is zero, too, continue compare,
6011 * b. if carry is set, then continue depending on cmpop ^ condition:
6012 * 1. '<' return false (literal < variable),
6013 * 2. '>' return true (literal > variable) */
6014 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6015 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6018 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6019 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6023 /* literal is negative:
6024 * a. if carry is set, too, continue compare,
6025 * b. if carry is zero, then continue depending on cmpop ^ condition:
6026 * 1. '<' return true (literal < variable),
6027 * 2. '>' return false (literal > variable) */
6028 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6029 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6031 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6032 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6037 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6039 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6040 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6045 pic16_emitpLabel( tlbl1->key );
6048 compareAopfirstpass=1;
6049 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6050 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6051 // pic16_emitpcode(POC_MOVWF, pct);
6053 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6054 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6055 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6056 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6060 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6061 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6062 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6063 // pic16_emitpcode(POC_MOVWF, pct);
6065 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6066 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6067 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6068 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6069 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6072 if(ifx)ifx->generated = 1;
6074 if(AOP_SIZE(result)) {
6075 pic16_emitpLabel(tlbl->key);
6076 pic16_emitpLabel(falselbl->key);
6077 pic16_outBitOp( result, pct2 );
6079 pic16_emitpLabel(tlbl->key);
6083 /* unsigned compare */
6084 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6086 compareAopfirstpass=1;
6089 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6090 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6093 if(ifx)ifx->generated = 1;
6095 if(AOP_SIZE(result)) {
6096 pic16_emitpLabel(falselbl->key);
6097 pic16_outBitC( result );
6102 /* compare registers */
6103 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6107 pCodeOp *pct, *pct2;
6109 /* signed compare */
6110 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6112 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6113 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6114 tlbl = newiTempLabel( NULL );
6116 compareAopfirstpass=1;
6119 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6120 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6121 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6122 pic16_emitpcode(POC_MOVWF, pct);
6124 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6125 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6126 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6128 /* WREG already holds left + 0x80 */
6129 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6132 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6133 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6134 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6135 pic16_emitpcode(POC_MOVWF, pct);
6137 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6138 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6139 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6141 /* WREG already holds left + 0x80 */
6142 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6143 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6146 if(ifx)ifx->generated = 1;
6148 if(AOP_SIZE(result)) {
6149 pic16_emitpLabel(tlbl->key);
6150 pic16_emitpLabel(falselbl->key);
6151 pic16_outBitOp( result, pct2 );
6153 pic16_emitpLabel(tlbl->key);
6157 /* unsigned compare */
6158 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6160 compareAopfirstpass=1;
6163 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6164 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6168 if(ifx)ifx->generated = 1;
6169 if(AOP_SIZE(result)) {
6171 pic16_emitpLabel(falselbl->key);
6172 pic16_outBitC( result );
6183 /*-----------------------------------------------------------------*/
6184 /* genCmpGt :- greater than comparison */
6185 /*-----------------------------------------------------------------*/
6186 static void genCmpGt (iCode *ic, iCode *ifx)
6188 operand *left, *right, *result;
6189 sym_link *letype , *retype;
6195 right= IC_RIGHT(ic);
6196 result = IC_RESULT(ic);
6198 letype = getSpec(operandType(left));
6199 retype =getSpec(operandType(right));
6200 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6201 /* assign the amsops */
6202 pic16_aopOp (left,ic,FALSE);
6203 pic16_aopOp (right,ic,FALSE);
6204 pic16_aopOp (result,ic,TRUE);
6206 genCmp(right, left, result, ifx, sign);
6208 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6209 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6210 pic16_freeAsmop(result,NULL,ic,TRUE);
6213 /*-----------------------------------------------------------------*/
6214 /* genCmpLt - less than comparisons */
6215 /*-----------------------------------------------------------------*/
6216 static void genCmpLt (iCode *ic, iCode *ifx)
6218 operand *left, *right, *result;
6219 sym_link *letype , *retype;
6225 right= IC_RIGHT(ic);
6226 result = IC_RESULT(ic);
6228 letype = getSpec(operandType(left));
6229 retype =getSpec(operandType(right));
6230 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6232 /* assign the amsops */
6233 pic16_aopOp (left,ic,FALSE);
6234 pic16_aopOp (right,ic,FALSE);
6235 pic16_aopOp (result,ic,TRUE);
6237 genCmp(left, right, result, ifx, sign);
6239 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6240 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6241 pic16_freeAsmop(result,NULL,ic,TRUE);
6246 // FIXME reenable literal optimisation when the pic16 port is stable
6248 /*-----------------------------------------------------------------*/
6249 /* genc16bit2lit - compare a 16 bit value to a literal */
6250 /*-----------------------------------------------------------------*/
6251 static void genc16bit2lit(operand *op, int lit, int offset)
6255 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6256 if( (lit&0xff) == 0)
6261 switch( BYTEofLONG(lit,i)) {
6263 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6266 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6269 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6272 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6273 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6278 switch( BYTEofLONG(lit,i)) {
6280 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6284 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6288 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6291 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6293 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6302 /*-----------------------------------------------------------------*/
6303 /* gencjneshort - compare and jump if not equal */
6304 /*-----------------------------------------------------------------*/
6305 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6307 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6309 int res_offset = 0; /* the result may be a different size then left or right */
6310 int res_size = AOP_SIZE(result);
6312 symbol *lbl, *lbl_done;
6314 unsigned long lit = 0L;
6315 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6317 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6318 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6320 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6321 resolveIfx(&rIfx,ifx);
6322 lbl = newiTempLabel(NULL);
6323 lbl_done = newiTempLabel(NULL);
6326 /* if the left side is a literal or
6327 if the right is in a pointer register and left
6329 if ((AOP_TYPE(left) == AOP_LIT) ||
6330 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6335 if(AOP_TYPE(right) == AOP_LIT)
6336 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6338 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6339 preserve_result = 1;
6341 if(result && !preserve_result)
6344 for(i = 0; i < AOP_SIZE(result); i++)
6345 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6349 /* if the right side is a literal then anything goes */
6350 if (AOP_TYPE(right) == AOP_LIT &&
6351 AOP_TYPE(left) != AOP_DIR ) {
6354 genc16bit2lit(left, lit, 0);
6356 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6359 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6362 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6363 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6365 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6369 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6371 if(res_offset < res_size-1)
6379 /* if the right side is in a register or in direct space or
6380 if the left is a pointer register & right is not */
6381 else if (AOP_TYPE(right) == AOP_REG ||
6382 AOP_TYPE(right) == AOP_DIR ||
6383 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6384 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6385 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6386 int lbl_key = lbl->key;
6389 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6390 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6392 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6393 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6394 __FUNCTION__,__LINE__);
6398 /* switch(size) { */
6400 /* genc16bit2lit(left, lit, 0); */
6402 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6407 if((AOP_TYPE(left) == AOP_DIR) &&
6408 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6410 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6411 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6413 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6415 switch (lit & 0xff) {
6417 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6420 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6421 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6422 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6426 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6427 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6428 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6429 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6433 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6434 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6439 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6442 if(AOP_TYPE(result) == AOP_CRY) {
6443 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6448 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6450 /* fix me. probably need to check result size too */
6451 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6456 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6457 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6464 if(res_offset < res_size-1)
6469 } else if(AOP_TYPE(right) == AOP_REG &&
6470 AOP_TYPE(left) != AOP_DIR){
6473 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6474 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6475 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6480 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6482 if(res_offset < res_size-1)
6487 /* right is a pointer reg need both a & b */
6489 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6491 pic16_emitcode("mov","b,%s",l);
6492 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6493 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6498 if(result && preserve_result)
6501 for(i = 0; i < AOP_SIZE(result); i++)
6502 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6505 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6507 if(result && preserve_result)
6508 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6511 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6513 pic16_emitpLabel(lbl->key);
6515 if(result && preserve_result)
6518 for(i = 0; i < AOP_SIZE(result); i++)
6519 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6521 pic16_emitpLabel(lbl_done->key);
6524 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6532 /*-----------------------------------------------------------------*/
6533 /* gencjne - compare and jump if not equal */
6534 /*-----------------------------------------------------------------*/
6535 static void gencjne(operand *left, operand *right, iCode *ifx)
6537 symbol *tlbl = newiTempLabel(NULL);
6539 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6540 gencjneshort(left, right, lbl);
6542 pic16_emitcode("mov","a,%s",one);
6543 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6544 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6545 pic16_emitcode("clr","a");
6546 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6548 pic16_emitpLabel(lbl->key);
6549 pic16_emitpLabel(tlbl->key);
6555 /*-----------------------------------------------------------------*/
6556 /* is_LitOp - check if operand has to be treated as literal */
6557 /*-----------------------------------------------------------------*/
6558 static bool is_LitOp(operand *op)
6560 return ((AOP_TYPE(op) == AOP_LIT)
6561 || ( (AOP_TYPE(op) == AOP_PCODE)
6562 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6563 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6566 /*-----------------------------------------------------------------*/
6567 /* is_LitAOp - check if operand has to be treated as literal */
6568 /*-----------------------------------------------------------------*/
6569 static bool is_LitAOp(asmop *aop)
6571 return ((aop->type == AOP_LIT)
6572 || ( (aop->type == AOP_PCODE)
6573 && ( (aop->aopu.pcop->type == PO_LITERAL)
6574 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6579 /*-----------------------------------------------------------------*/
6580 /* genCmpEq - generates code for equal to */
6581 /*-----------------------------------------------------------------*/
6582 static void genCmpEq (iCode *ic, iCode *ifx)
6584 operand *left, *right, *result;
6585 symbol *falselbl = newiTempLabel(NULL);
6586 symbol *donelbl = newiTempLabel(NULL);
6588 int preserve_result = 0;
6589 int generate_result = 0;
6591 unsigned long lit = -1;
6595 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6596 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6597 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6599 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6601 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6603 werror(W_POSSBUG2, __FILE__, __LINE__);
6604 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6605 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6609 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6611 operand *tmp = right ;
6616 if (AOP_TYPE(right) == AOP_LIT) {
6617 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6620 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6621 preserve_result = 1;
6623 if(result && AOP_SIZE(result))
6624 generate_result = 1;
6626 if(generate_result && !preserve_result)
6628 for(i = 0; i < AOP_SIZE(result); i++)
6629 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6632 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6633 for(i=0; i < AOP_SIZE(left); i++)
6635 if(AOP_TYPE(left) != AOP_ACC)
6638 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6640 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6642 if(is_LitOp(right)) {
6643 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6644 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6647 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6649 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6654 if(generate_result && preserve_result)
6656 for(i = 0; i < AOP_SIZE(result); i++)
6657 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6661 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6663 if(generate_result && preserve_result)
6664 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6666 if(ifx && IC_TRUE(ifx))
6667 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6669 if(ifx && IC_FALSE(ifx))
6670 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6672 pic16_emitpLabel(falselbl->key);
6676 if(ifx && IC_FALSE(ifx))
6677 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6679 if(generate_result && preserve_result)
6681 for(i = 0; i < AOP_SIZE(result); i++)
6682 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6685 pic16_emitpLabel(donelbl->key);
6691 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6692 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6693 pic16_freeAsmop(result,NULL,ic,TRUE);
6699 // old version kept for reference
6701 /*-----------------------------------------------------------------*/
6702 /* genCmpEq - generates code for equal to */
6703 /*-----------------------------------------------------------------*/
6704 static void genCmpEq (iCode *ic, iCode *ifx)
6706 operand *left, *right, *result;
6707 unsigned long lit = 0L;
6709 symbol *falselbl = newiTempLabel(NULL);
6712 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6715 DEBUGpic16_emitcode ("; ifx is non-null","");
6717 DEBUGpic16_emitcode ("; ifx is null","");
6719 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6720 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6721 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6723 size = max(AOP_SIZE(left),AOP_SIZE(right));
6725 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6727 /* if literal, literal on the right or
6728 if the right is in a pointer register and left
6730 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6731 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6732 operand *tmp = right ;
6738 if(ifx && !AOP_SIZE(result)){
6740 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6741 /* if they are both bit variables */
6742 if (AOP_TYPE(left) == AOP_CRY &&
6743 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6744 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6745 if(AOP_TYPE(right) == AOP_LIT){
6746 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6748 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6749 pic16_emitcode("cpl","c");
6750 } else if(lit == 1L) {
6751 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6753 pic16_emitcode("clr","c");
6755 /* AOP_TYPE(right) == AOP_CRY */
6757 symbol *lbl = newiTempLabel(NULL);
6758 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6759 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6760 pic16_emitcode("cpl","c");
6761 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6763 /* if true label then we jump if condition
6765 tlbl = newiTempLabel(NULL);
6766 if ( IC_TRUE(ifx) ) {
6767 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6768 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6770 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6771 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6773 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6776 /* left and right are both bit variables, result is carry */
6779 resolveIfx(&rIfx,ifx);
6781 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6782 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6783 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6784 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6789 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6791 /* They're not both bit variables. Is the right a literal? */
6792 if(AOP_TYPE(right) == AOP_LIT) {
6793 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6798 switch(lit & 0xff) {
6800 if ( IC_TRUE(ifx) ) {
6801 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6803 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6805 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6806 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6810 if ( IC_TRUE(ifx) ) {
6811 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6813 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6815 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6816 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6820 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6822 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6827 /* end of size == 1 */
6831 genc16bit2lit(left,lit,offset);
6834 /* end of size == 2 */
6839 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6840 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6841 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6842 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6845 /* search for patterns that can be optimized */
6847 genc16bit2lit(left,lit,0);
6851 emitSKPZ; // if hi word unequal
6853 emitSKPNZ; // if hi word equal
6855 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6856 genc16bit2lit(left,lit,2);
6859 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6860 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6864 pic16_emitpLabel(falselbl->key);
6873 } else if(AOP_TYPE(right) == AOP_CRY ) {
6874 /* we know the left is not a bit, but that the right is */
6875 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6876 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6877 pic16_popGet(AOP(right),offset));
6878 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6880 /* if the two are equal, then W will be 0 and the Z bit is set
6881 * we could test Z now, or go ahead and check the high order bytes if
6882 * the variable we're comparing is larger than a byte. */
6885 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6887 if ( IC_TRUE(ifx) ) {
6889 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6890 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6893 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6894 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6898 /* They're both variables that are larger than bits */
6901 tlbl = newiTempLabel(NULL);
6904 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6905 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6907 if ( IC_TRUE(ifx) ) {
6911 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6913 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6914 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6918 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6921 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6922 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6927 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6929 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6930 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6934 if(s>1 && IC_TRUE(ifx)) {
6935 pic16_emitpLabel(tlbl->key);
6936 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6940 /* mark the icode as generated */
6945 /* if they are both bit variables */
6946 if (AOP_TYPE(left) == AOP_CRY &&
6947 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6948 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
6949 if(AOP_TYPE(right) == AOP_LIT){
6950 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6952 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6953 pic16_emitcode("cpl","c");
6954 } else if(lit == 1L) {
6955 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6957 pic16_emitcode("clr","c");
6959 /* AOP_TYPE(right) == AOP_CRY */
6961 symbol *lbl = newiTempLabel(NULL);
6962 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6963 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6964 pic16_emitcode("cpl","c");
6965 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6968 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6969 pic16_outBitC(result);
6973 genIfxJump (ifx,"c");
6976 /* if the result is used in an arithmetic operation
6977 then put the result in place */
6978 pic16_outBitC(result);
6981 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
6982 gencjne(left,right,result,ifx);
6985 gencjne(left,right,newiTempLabel(NULL));
6987 if(IC_TRUE(ifx)->key)
6988 gencjne(left,right,IC_TRUE(ifx)->key);
6990 gencjne(left,right,IC_FALSE(ifx)->key);
6994 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6995 pic16_aopPut(AOP(result),"a",0);
7000 genIfxJump (ifx,"a");
7004 /* if the result is used in an arithmetic operation
7005 then put the result in place */
7007 if (AOP_TYPE(result) != AOP_CRY)
7008 pic16_outAcc(result);
7010 /* leave the result in acc */
7014 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7015 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7016 pic16_freeAsmop(result,NULL,ic,TRUE);
7020 /*-----------------------------------------------------------------*/
7021 /* ifxForOp - returns the icode containing the ifx for operand */
7022 /*-----------------------------------------------------------------*/
7023 static iCode *ifxForOp ( operand *op, iCode *ic )
7027 /* if true symbol then needs to be assigned */
7028 if (IS_TRUE_SYMOP(op))
7031 /* if this has register type condition and
7032 the next instruction is ifx with the same operand
7033 and live to of the operand is upto the ifx only then */
7035 && ic->next->op == IFX
7036 && IC_COND(ic->next)->key == op->key
7037 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7039 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7045 ic->next->op == IFX &&
7046 IC_COND(ic->next)->key == op->key) {
7047 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7052 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7054 ic->next->op == IFX)
7055 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7058 ic->next->op == IFX &&
7059 IC_COND(ic->next)->key == op->key) {
7060 DEBUGpic16_emitcode ("; "," key is okay");
7061 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7062 OP_SYMBOL(op)->liveTo,
7067 /* the code below is completely untested
7068 * it just allows ulong2fs.c compile -- VR */
7071 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7072 __FILE__, __FUNCTION__, __LINE__);
7074 /* if this has register type condition and
7075 the next instruction is ifx with the same operand
7076 and live to of the operand is upto the ifx only then */
7078 ic->next->op == IFX &&
7079 IC_COND(ic->next)->key == op->key &&
7080 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7084 ic->next->op == IFX &&
7085 IC_COND(ic->next)->key == op->key) {
7086 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7090 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7091 __FILE__, __FUNCTION__, __LINE__);
7093 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7098 /*-----------------------------------------------------------------*/
7099 /* genAndOp - for && operation */
7100 /*-----------------------------------------------------------------*/
7101 static void genAndOp (iCode *ic)
7103 operand *left,*right, *result;
7108 /* note here that && operations that are in an
7109 if statement are taken away by backPatchLabels
7110 only those used in arthmetic operations remain */
7111 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7112 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7113 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7115 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7117 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7118 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7119 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7121 /* if both are bit variables */
7122 /* if (AOP_TYPE(left) == AOP_CRY && */
7123 /* AOP_TYPE(right) == AOP_CRY ) { */
7124 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7125 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7126 /* pic16_outBitC(result); */
7128 /* tlbl = newiTempLabel(NULL); */
7129 /* pic16_toBoolean(left); */
7130 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7131 /* pic16_toBoolean(right); */
7132 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7133 /* pic16_outBitAcc(result); */
7136 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7137 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7138 pic16_freeAsmop(result,NULL,ic,TRUE);
7142 /*-----------------------------------------------------------------*/
7143 /* genOrOp - for || operation */
7144 /*-----------------------------------------------------------------*/
7147 modified this code, but it doesn't appear to ever get called
7150 static void genOrOp (iCode *ic)
7152 operand *left,*right, *result;
7157 /* note here that || operations that are in an
7158 if statement are taken away by backPatchLabels
7159 only those used in arthmetic operations remain */
7160 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7161 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7162 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7164 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7166 /* if both are bit variables */
7167 if (AOP_TYPE(left) == AOP_CRY &&
7168 AOP_TYPE(right) == AOP_CRY ) {
7169 pic16_emitcode("clrc","");
7170 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7171 AOP(left)->aopu.aop_dir,
7172 AOP(left)->aopu.aop_dir);
7173 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7174 AOP(right)->aopu.aop_dir,
7175 AOP(right)->aopu.aop_dir);
7176 pic16_emitcode("setc","");
7179 tlbl = newiTempLabel(NULL);
7180 pic16_toBoolean(left);
7182 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7183 pic16_toBoolean(right);
7184 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7186 pic16_outBitAcc(result);
7189 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7190 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7191 pic16_freeAsmop(result,NULL,ic,TRUE);
7194 /*-----------------------------------------------------------------*/
7195 /* isLiteralBit - test if lit == 2^n */
7196 /*-----------------------------------------------------------------*/
7197 static int isLiteralBit(unsigned long lit)
7199 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7200 0x100L,0x200L,0x400L,0x800L,
7201 0x1000L,0x2000L,0x4000L,0x8000L,
7202 0x10000L,0x20000L,0x40000L,0x80000L,
7203 0x100000L,0x200000L,0x400000L,0x800000L,
7204 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7205 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7208 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7209 for(idx = 0; idx < 32; idx++)
7215 /*-----------------------------------------------------------------*/
7216 /* continueIfTrue - */
7217 /*-----------------------------------------------------------------*/
7218 static void continueIfTrue (iCode *ic)
7222 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7226 /*-----------------------------------------------------------------*/
7228 /*-----------------------------------------------------------------*/
7229 static void jumpIfTrue (iCode *ic)
7233 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7237 /*-----------------------------------------------------------------*/
7238 /* jmpTrueOrFalse - */
7239 /*-----------------------------------------------------------------*/
7240 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7242 // ugly but optimized by peephole
7245 symbol *nlbl = newiTempLabel(NULL);
7246 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7247 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7248 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7249 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7251 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7252 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7257 /*-----------------------------------------------------------------*/
7258 /* genAnd - code for and */
7259 /*-----------------------------------------------------------------*/
7260 static void genAnd (iCode *ic, iCode *ifx)
7262 operand *left, *right, *result;
7264 unsigned long lit = 0L;
7270 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7271 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7272 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7274 resolveIfx(&rIfx,ifx);
7276 /* if left is a literal & right is not then exchange them */
7277 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7278 AOP_NEEDSACC(left)) {
7279 operand *tmp = right ;
7284 /* if result = right then exchange them */
7285 if(pic16_sameRegs(AOP(result),AOP(right))){
7286 operand *tmp = right ;
7291 /* if right is bit then exchange them */
7292 if (AOP_TYPE(right) == AOP_CRY &&
7293 AOP_TYPE(left) != AOP_CRY){
7294 operand *tmp = right ;
7298 if(AOP_TYPE(right) == AOP_LIT)
7299 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7301 size = AOP_SIZE(result);
7303 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7306 // result = bit & yy;
7307 if (AOP_TYPE(left) == AOP_CRY){
7308 // c = bit & literal;
7309 if(AOP_TYPE(right) == AOP_LIT){
7311 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7314 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7317 if(size && (AOP_TYPE(result) == AOP_CRY)){
7318 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7321 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7325 pic16_emitcode("clr","c");
7328 if (AOP_TYPE(right) == AOP_CRY){
7330 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7331 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7334 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7336 pic16_emitcode("rrc","a");
7337 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7343 pic16_outBitC(result);
7345 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7346 genIfxJump(ifx, "c");
7350 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7351 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7352 if((AOP_TYPE(right) == AOP_LIT) &&
7353 (AOP_TYPE(result) == AOP_CRY) &&
7354 (AOP_TYPE(left) != AOP_CRY)){
7355 int posbit = isLiteralBit(lit);
7359 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7362 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7368 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7369 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7371 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7372 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7375 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7376 size = AOP_SIZE(left);
7379 int bp = posbit, ofs=0;
7386 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7387 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7391 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7392 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7394 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7401 symbol *tlbl = newiTempLabel(NULL);
7402 int sizel = AOP_SIZE(left);
7408 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7410 /* patch provided by Aaron Colwell */
7411 if((posbit = isLiteralBit(bytelit)) != 0) {
7412 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7413 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7414 (posbit-1),0, PO_GPR_REGISTER));
7416 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7417 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7419 if (bytelit == 0xff) {
7420 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7421 * a peephole could optimize it out -- VR */
7422 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7424 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7425 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7428 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7429 pic16_popGetLabel(tlbl->key));
7433 /* old code, left here for reference -- VR 09/2004 */
7434 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7436 if((posbit = isLiteralBit(bytelit)) != 0)
7437 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7439 if(bytelit != 0x0FFL)
7440 pic16_emitcode("anl","a,%s",
7441 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7442 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7448 // bit = left & literal
7451 pic16_emitpLabel(tlbl->key);
7453 // if(left & literal)
7456 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7459 pic16_emitpLabel(tlbl->key);
7464 pic16_outBitC(result);
7468 /* if left is same as result */
7469 if(pic16_sameRegs(AOP(result),AOP(left))){
7471 for(;size--; offset++,lit>>=8) {
7472 if(AOP_TYPE(right) == AOP_LIT){
7473 switch(lit & 0xff) {
7475 /* and'ing with 0 has clears the result */
7476 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7477 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7480 /* and'ing with 0xff is a nop when the result and left are the same */
7485 int p = pic16_my_powof2( (~lit) & 0xff );
7487 /* only one bit is set in the literal, so use a bcf instruction */
7488 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7489 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7492 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7493 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7494 if(know_W != (lit&0xff))
7495 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7497 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7502 if (AOP_TYPE(left) == AOP_ACC) {
7503 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7505 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7506 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7513 // left & result in different registers
7514 if(AOP_TYPE(result) == AOP_CRY){
7516 // if(size), result in bit
7517 // if(!size && ifx), conditional oper: if(left & right)
7518 symbol *tlbl = newiTempLabel(NULL);
7519 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7521 pic16_emitcode("setb","c");
7523 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7524 pic16_emitcode("anl","a,%s",
7525 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7526 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7531 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7532 pic16_outBitC(result);
7534 jmpTrueOrFalse(ifx, tlbl);
7536 for(;(size--);offset++) {
7538 // result = left & right
7539 if(AOP_TYPE(right) == AOP_LIT){
7540 int t = (lit >> (offset*8)) & 0x0FFL;
7543 pic16_emitcode("clrf","%s",
7544 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7545 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7548 pic16_emitcode("movf","%s,w",
7549 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7550 pic16_emitcode("movwf","%s",
7551 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7552 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7553 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7556 pic16_emitcode("movlw","0x%x",t);
7557 pic16_emitcode("andwf","%s,w",
7558 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7559 pic16_emitcode("movwf","%s",
7560 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7562 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7563 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7564 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7569 if (AOP_TYPE(left) == AOP_ACC) {
7570 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7571 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7573 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7574 pic16_emitcode("andwf","%s,w",
7575 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7576 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7577 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7579 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7580 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7586 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7587 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7588 pic16_freeAsmop(result,NULL,ic,TRUE);
7591 /*-----------------------------------------------------------------*/
7592 /* genOr - code for or */
7593 /*-----------------------------------------------------------------*/
7594 static void genOr (iCode *ic, iCode *ifx)
7596 operand *left, *right, *result;
7598 unsigned long lit = 0L;
7600 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7602 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7603 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7604 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7606 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7608 /* if left is a literal & right is not then exchange them */
7609 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7610 AOP_NEEDSACC(left)) {
7611 operand *tmp = right ;
7616 /* if result = right then exchange them */
7617 if(pic16_sameRegs(AOP(result),AOP(right))){
7618 operand *tmp = right ;
7623 /* if right is bit then exchange them */
7624 if (AOP_TYPE(right) == AOP_CRY &&
7625 AOP_TYPE(left) != AOP_CRY){
7626 operand *tmp = right ;
7631 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7633 if(AOP_TYPE(right) == AOP_LIT)
7634 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7636 size = AOP_SIZE(result);
7640 if (AOP_TYPE(left) == AOP_CRY){
7641 if(AOP_TYPE(right) == AOP_LIT){
7642 // c = bit & literal;
7644 // lit != 0 => result = 1
7645 if(AOP_TYPE(result) == AOP_CRY){
7647 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7648 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7649 // AOP(result)->aopu.aop_dir,
7650 // AOP(result)->aopu.aop_dir);
7652 continueIfTrue(ifx);
7656 // lit == 0 => result = left
7657 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7659 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7662 if (AOP_TYPE(right) == AOP_CRY){
7663 if(pic16_sameRegs(AOP(result),AOP(left))){
7665 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7666 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7667 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7669 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7670 AOP(result)->aopu.aop_dir,
7671 AOP(result)->aopu.aop_dir);
7672 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7673 AOP(right)->aopu.aop_dir,
7674 AOP(right)->aopu.aop_dir);
7675 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7676 AOP(result)->aopu.aop_dir,
7677 AOP(result)->aopu.aop_dir);
7679 if( AOP_TYPE(result) == AOP_ACC) {
7680 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7681 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7682 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7683 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7687 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7688 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7689 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7690 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7692 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7693 AOP(result)->aopu.aop_dir,
7694 AOP(result)->aopu.aop_dir);
7695 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7696 AOP(right)->aopu.aop_dir,
7697 AOP(right)->aopu.aop_dir);
7698 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7699 AOP(left)->aopu.aop_dir,
7700 AOP(left)->aopu.aop_dir);
7701 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7702 AOP(result)->aopu.aop_dir,
7703 AOP(result)->aopu.aop_dir);
7708 symbol *tlbl = newiTempLabel(NULL);
7709 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7712 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7713 if( AOP_TYPE(right) == AOP_ACC) {
7714 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7716 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7717 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7722 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7723 pic16_emitcode(";XXX setb","c");
7724 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7725 AOP(left)->aopu.aop_dir,tlbl->key+100);
7726 pic16_toBoolean(right);
7727 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7728 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7729 jmpTrueOrFalse(ifx, tlbl);
7733 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7740 pic16_outBitC(result);
7742 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7743 genIfxJump(ifx, "c");
7747 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7748 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7749 if((AOP_TYPE(right) == AOP_LIT) &&
7750 (AOP_TYPE(result) == AOP_CRY) &&
7751 (AOP_TYPE(left) != AOP_CRY)){
7753 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7756 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7758 continueIfTrue(ifx);
7761 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7762 // lit = 0, result = boolean(left)
7764 pic16_emitcode(";XXX setb","c");
7765 pic16_toBoolean(right);
7767 symbol *tlbl = newiTempLabel(NULL);
7768 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7770 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7772 genIfxJump (ifx,"a");
7776 pic16_outBitC(result);
7780 /* if left is same as result */
7781 if(pic16_sameRegs(AOP(result),AOP(left))){
7783 for(;size--; offset++,lit>>=8) {
7784 if(AOP_TYPE(right) == AOP_LIT){
7785 if((lit & 0xff) == 0)
7786 /* or'ing with 0 has no effect */
7789 int p = pic16_my_powof2(lit & 0xff);
7791 /* only one bit is set in the literal, so use a bsf instruction */
7792 pic16_emitpcode(POC_BSF,
7793 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7795 if(know_W != (lit & 0xff))
7796 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7797 know_W = lit & 0xff;
7798 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7803 if (AOP_TYPE(left) == AOP_ACC) {
7804 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7805 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7807 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7808 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7810 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7811 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7817 // left & result in different registers
7818 if(AOP_TYPE(result) == AOP_CRY){
7820 // if(size), result in bit
7821 // if(!size && ifx), conditional oper: if(left | right)
7822 symbol *tlbl = newiTempLabel(NULL);
7823 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7824 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7828 pic16_emitcode(";XXX setb","c");
7830 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7831 pic16_emitcode(";XXX orl","a,%s",
7832 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7833 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7838 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7839 pic16_outBitC(result);
7841 jmpTrueOrFalse(ifx, tlbl);
7842 } else for(;(size--);offset++){
7844 // result = left & right
7845 if(AOP_TYPE(right) == AOP_LIT){
7846 int t = (lit >> (offset*8)) & 0x0FFL;
7849 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7850 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7852 pic16_emitcode("movf","%s,w",
7853 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7854 pic16_emitcode("movwf","%s",
7855 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7858 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7859 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7860 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7862 pic16_emitcode("movlw","0x%x",t);
7863 pic16_emitcode("iorwf","%s,w",
7864 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7865 pic16_emitcode("movwf","%s",
7866 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7872 // faster than result <- left, anl result,right
7873 // and better if result is SFR
7874 if (AOP_TYPE(left) == AOP_ACC) {
7875 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7876 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7878 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7879 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7881 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7882 pic16_emitcode("iorwf","%s,w",
7883 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7885 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7886 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7891 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7892 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7893 pic16_freeAsmop(result,NULL,ic,TRUE);
7896 /*-----------------------------------------------------------------*/
7897 /* genXor - code for xclusive or */
7898 /*-----------------------------------------------------------------*/
7899 static void genXor (iCode *ic, iCode *ifx)
7901 operand *left, *right, *result;
7903 unsigned long lit = 0L;
7905 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7907 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7908 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7909 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7911 /* if left is a literal & right is not ||
7912 if left needs acc & right does not */
7913 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7914 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7915 operand *tmp = right ;
7920 /* if result = right then exchange them */
7921 if(pic16_sameRegs(AOP(result),AOP(right))){
7922 operand *tmp = right ;
7927 /* if right is bit then exchange them */
7928 if (AOP_TYPE(right) == AOP_CRY &&
7929 AOP_TYPE(left) != AOP_CRY){
7930 operand *tmp = right ;
7934 if(AOP_TYPE(right) == AOP_LIT)
7935 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7937 size = AOP_SIZE(result);
7941 if (AOP_TYPE(left) == AOP_CRY){
7942 if(AOP_TYPE(right) == AOP_LIT){
7943 // c = bit & literal;
7945 // lit>>1 != 0 => result = 1
7946 if(AOP_TYPE(result) == AOP_CRY){
7948 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
7949 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7951 continueIfTrue(ifx);
7954 pic16_emitcode("setb","c");
7958 // lit == 0, result = left
7959 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7961 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7963 // lit == 1, result = not(left)
7964 if(size && pic16_sameRegs(AOP(result),AOP(left))){
7965 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
7966 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
7967 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7970 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7971 pic16_emitcode("cpl","c");
7978 symbol *tlbl = newiTempLabel(NULL);
7979 if (AOP_TYPE(right) == AOP_CRY){
7981 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7984 int sizer = AOP_SIZE(right);
7986 // if val>>1 != 0, result = 1
7987 pic16_emitcode("setb","c");
7989 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7991 // test the msb of the lsb
7992 pic16_emitcode("anl","a,#0xfe");
7993 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7997 pic16_emitcode("rrc","a");
7999 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8000 pic16_emitcode("cpl","c");
8001 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8006 pic16_outBitC(result);
8008 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8009 genIfxJump(ifx, "c");
8013 if(pic16_sameRegs(AOP(result),AOP(left))){
8014 /* if left is same as result */
8015 for(;size--; offset++) {
8016 if(AOP_TYPE(right) == AOP_LIT){
8017 int t = (lit >> (offset*8)) & 0x0FFL;
8021 if (IS_AOP_PREG(left)) {
8022 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8023 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8024 pic16_aopPut(AOP(result),"a",offset);
8026 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8027 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8028 pic16_emitcode("xrl","%s,%s",
8029 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8030 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8033 if (AOP_TYPE(left) == AOP_ACC)
8034 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8036 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8037 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8039 if (IS_AOP_PREG(left)) {
8040 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8041 pic16_aopPut(AOP(result),"a",offset);
8043 pic16_emitcode("xrl","%s,a",
8044 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8050 // left & result in different registers
8051 if(AOP_TYPE(result) == AOP_CRY){
8053 // if(size), result in bit
8054 // if(!size && ifx), conditional oper: if(left ^ right)
8055 symbol *tlbl = newiTempLabel(NULL);
8056 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8058 pic16_emitcode("setb","c");
8060 if((AOP_TYPE(right) == AOP_LIT) &&
8061 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8062 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8064 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8065 pic16_emitcode("xrl","a,%s",
8066 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8068 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8073 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8074 pic16_outBitC(result);
8076 jmpTrueOrFalse(ifx, tlbl);
8077 } else for(;(size--);offset++){
8079 // result = left & right
8080 if(AOP_TYPE(right) == AOP_LIT){
8081 int t = (lit >> (offset*8)) & 0x0FFL;
8084 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8085 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8086 pic16_emitcode("movf","%s,w",
8087 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8088 pic16_emitcode("movwf","%s",
8089 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8092 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8093 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8094 pic16_emitcode("comf","%s,w",
8095 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8096 pic16_emitcode("movwf","%s",
8097 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8100 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8101 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8102 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8103 pic16_emitcode("movlw","0x%x",t);
8104 pic16_emitcode("xorwf","%s,w",
8105 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8106 pic16_emitcode("movwf","%s",
8107 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8113 // faster than result <- left, anl result,right
8114 // and better if result is SFR
8115 if (AOP_TYPE(left) == AOP_ACC) {
8116 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8117 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8119 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8120 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8121 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8122 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8124 if ( AOP_TYPE(result) != AOP_ACC){
8125 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8126 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8132 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8133 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8134 pic16_freeAsmop(result,NULL,ic,TRUE);
8137 /*-----------------------------------------------------------------*/
8138 /* genInline - write the inline code out */
8139 /*-----------------------------------------------------------------*/
8140 static void genInline (iCode *ic)
8142 char *buffer, *bp, *bp1;
8144 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8146 _G.inLine += (!options.asmpeep);
8148 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8149 strcpy(buffer,IC_INLINE(ic));
8151 while((bp1=strstr(bp, "\\n"))) {
8159 /* This is an experimental code for #pragma inline
8160 and is temporarily disabled for 2.5.0 release */
8168 cbuf = Safe_strdup(buffer);
8169 cblen = strlen(buffer)+1;
8170 memset(cbuf, 0, cblen);
8175 if(*bp != '%')*bp1++ = *bp++;
8181 if(i>elementsInSet(asmInlineMap))break;
8184 s = indexSet(asmInlineMap, i);
8185 DEBUGpc("searching symbol s = `%s'", s);
8186 sym = findSym(SymbolTab, NULL, s);
8189 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8191 strcat(bp1, sym->rname);
8197 if(strlen(bp1) > cblen - 16) {
8198 int i = strlen(cbuf);
8200 cbuf = realloc(cbuf, cblen);
8201 memset(cbuf+i, 0, 50);
8207 buffer = Safe_strdup( cbuf );
8214 /* emit each line as a code */
8220 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8228 /* print label, use this special format with NULL directive
8229 * to denote that the argument should not be indented with tab */
8230 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8233 /* advance to end of line (prevent splitting of comments at ':' */
8234 while (*bp && *bp != '\n') {
8242 if ((bp1 != bp) && *bp1)
8243 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8248 _G.inLine -= (!options.asmpeep);
8251 /*-----------------------------------------------------------------*/
8252 /* genRRC - rotate right with carry */
8253 /*-----------------------------------------------------------------*/
8254 static void genRRC (iCode *ic)
8256 operand *left , *result ;
8257 int size, offset = 0, same;
8259 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8261 /* rotate right with carry */
8263 result=IC_RESULT(ic);
8264 pic16_aopOp (left,ic,FALSE);
8265 pic16_aopOp (result,ic,TRUE);
8267 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8269 same = pic16_sameRegs(AOP(result),AOP(left));
8271 size = AOP_SIZE(result);
8273 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8275 /* get the lsb and put it into the carry */
8276 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8283 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8285 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8286 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8292 pic16_freeAsmop(left,NULL,ic,TRUE);
8293 pic16_freeAsmop(result,NULL,ic,TRUE);
8296 /*-----------------------------------------------------------------*/
8297 /* genRLC - generate code for rotate left with carry */
8298 /*-----------------------------------------------------------------*/
8299 static void genRLC (iCode *ic)
8301 operand *left , *result ;
8302 int size, offset = 0;
8305 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8306 /* rotate right with carry */
8308 result=IC_RESULT(ic);
8309 pic16_aopOp (left,ic,FALSE);
8310 pic16_aopOp (result,ic,TRUE);
8312 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8314 same = pic16_sameRegs(AOP(result),AOP(left));
8316 /* move it to the result */
8317 size = AOP_SIZE(result);
8319 /* get the msb and put it into the carry */
8320 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8327 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8329 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8330 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8337 pic16_freeAsmop(left,NULL,ic,TRUE);
8338 pic16_freeAsmop(result,NULL,ic,TRUE);
8342 /* gpasm can get the highest order bit with HIGH/UPPER
8343 * so the following probably is not needed -- VR */
8345 /*-----------------------------------------------------------------*/
8346 /* genGetHbit - generates code get highest order bit */
8347 /*-----------------------------------------------------------------*/
8348 static void genGetHbit (iCode *ic)
8350 operand *left, *result;
8352 result=IC_RESULT(ic);
8353 pic16_aopOp (left,ic,FALSE);
8354 pic16_aopOp (result,ic,FALSE);
8356 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8357 /* get the highest order byte into a */
8358 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8359 if(AOP_TYPE(result) == AOP_CRY){
8360 pic16_emitcode("rlc","a");
8361 pic16_outBitC(result);
8364 pic16_emitcode("rl","a");
8365 pic16_emitcode("anl","a,#0x01");
8366 pic16_outAcc(result);
8370 pic16_freeAsmop(left,NULL,ic,TRUE);
8371 pic16_freeAsmop(result,NULL,ic,TRUE);
8375 /*-----------------------------------------------------------------*/
8376 /* AccRol - rotate left accumulator by known count */
8377 /*-----------------------------------------------------------------*/
8378 static void AccRol (int shCount)
8380 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8381 shCount &= 0x0007; // shCount : 0..7
8386 pic16_emitcode("rl","a");
8389 pic16_emitcode("rl","a");
8390 pic16_emitcode("rl","a");
8393 pic16_emitcode("swap","a");
8394 pic16_emitcode("rr","a");
8397 pic16_emitcode("swap","a");
8400 pic16_emitcode("swap","a");
8401 pic16_emitcode("rl","a");
8404 pic16_emitcode("rr","a");
8405 pic16_emitcode("rr","a");
8408 pic16_emitcode("rr","a");
8414 /*-----------------------------------------------------------------*/
8415 /* AccLsh - left shift accumulator by known count */
8416 /*-----------------------------------------------------------------*/
8417 static void AccLsh (int shCount)
8419 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8425 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8428 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8429 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8432 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8433 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8436 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8439 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8440 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8443 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8444 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8447 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8451 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8454 /*-----------------------------------------------------------------*/
8455 /* AccRsh - right shift accumulator by known count */
8456 /*-----------------------------------------------------------------*/
8457 static void AccRsh (int shCount, int andmask)
8459 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8464 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8467 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8468 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8471 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8472 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8475 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8478 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8479 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8482 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8483 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8486 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8491 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8493 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8497 /*-----------------------------------------------------------------*/
8498 /* AccSRsh - signed right shift accumulator by known count */
8499 /*-----------------------------------------------------------------*/
8500 static void AccSRsh (int shCount)
8503 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8506 pic16_emitcode("mov","c,acc.7");
8507 pic16_emitcode("rrc","a");
8508 } else if(shCount == 2){
8509 pic16_emitcode("mov","c,acc.7");
8510 pic16_emitcode("rrc","a");
8511 pic16_emitcode("mov","c,acc.7");
8512 pic16_emitcode("rrc","a");
8514 tlbl = newiTempLabel(NULL);
8515 /* rotate right accumulator */
8516 AccRol(8 - shCount);
8517 /* and kill the higher order bits */
8518 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8519 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8520 pic16_emitcode("orl","a,#0x%02x",
8521 (unsigned char)~SRMask[shCount]);
8522 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8528 /*-----------------------------------------------------------------*/
8529 /* shiftR1Left2Result - shift right one byte from left to result */
8530 /*-----------------------------------------------------------------*/
8531 static void shiftR1Left2ResultSigned (operand *left, int offl,
8532 operand *result, int offr,
8537 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8539 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8543 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8545 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8547 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8548 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8554 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8556 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8558 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8559 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8561 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8562 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8568 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8570 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8571 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8574 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8575 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8576 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8578 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8579 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8581 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8585 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8586 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8587 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8588 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8589 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8593 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8595 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8596 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8598 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8599 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8600 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8601 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8602 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8607 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8608 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8609 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8610 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8611 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8612 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8614 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8615 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8616 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8617 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8618 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8624 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8625 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8626 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8627 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8629 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8630 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8631 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8639 /*-----------------------------------------------------------------*/
8640 /* shiftR1Left2Result - shift right one byte from left to result */
8641 /*-----------------------------------------------------------------*/
8642 static void shiftR1Left2Result (operand *left, int offl,
8643 operand *result, int offr,
8644 int shCount, int sign)
8648 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8650 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8652 /* Copy the msb into the carry if signed. */
8654 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8664 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8666 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8667 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8673 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8675 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8676 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8679 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8684 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8686 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8687 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8690 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8691 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8692 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8693 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8697 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8698 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8699 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8703 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8704 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8705 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8707 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8712 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8713 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8714 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8715 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8716 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8721 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8722 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8723 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8732 /*-----------------------------------------------------------------*/
8733 /* shiftL1Left2Result - shift left one byte from left to result */
8734 /*-----------------------------------------------------------------*/
8735 static void shiftL1Left2Result (operand *left, int offl,
8736 operand *result, int offr, int shCount)
8741 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8743 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8744 DEBUGpic16_emitcode ("; ***","same = %d",same);
8745 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8747 /* shift left accumulator */
8748 //AccLsh(shCount); // don't comment out just yet...
8749 // pic16_aopPut(AOP(result),"a",offr);
8753 /* Shift left 1 bit position */
8754 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8756 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8758 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8759 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8763 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8764 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8765 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8766 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8769 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8770 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8771 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8772 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8773 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8776 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8777 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8778 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8781 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8782 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8783 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8784 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8787 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8788 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8789 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8790 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8791 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8794 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8795 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8796 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8800 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8805 /*-----------------------------------------------------------------*/
8806 /* movLeft2Result - move byte from left to result */
8807 /*-----------------------------------------------------------------*/
8808 static void movLeft2Result (operand *left, int offl,
8809 operand *result, int offr)
8812 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8813 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8814 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8816 if (*l == '@' && (IS_AOP_PREG(result))) {
8817 pic16_emitcode("mov","a,%s",l);
8818 pic16_aopPut(AOP(result),"a",offr);
8820 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8821 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8826 /*-----------------------------------------------------------------*/
8827 /* shiftL2Left2Result - shift left two bytes from left to result */
8828 /*-----------------------------------------------------------------*/
8829 static void shiftL2Left2Result (operand *left, int offl,
8830 operand *result, int offr, int shCount)
8832 int same = pic16_sameRegs(AOP(result), AOP(left));
8835 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8837 if (same && (offl != offr)) { // shift bytes
8840 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8841 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8843 } else { // just treat as different later on
8856 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8857 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8858 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8862 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8863 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8869 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8870 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8871 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8872 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8873 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8874 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8875 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8877 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8878 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8882 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8883 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8884 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8885 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8886 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8887 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8888 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8889 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8890 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8891 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8894 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8895 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8896 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8897 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8898 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8908 /* note, use a mov/add for the shift since the mov has a
8909 chance of getting optimized out */
8910 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8911 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8912 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8913 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8914 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8918 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8919 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8925 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8926 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8927 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8928 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8929 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8930 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8931 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8932 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8936 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8937 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8941 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8942 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8943 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8944 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8946 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8947 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8948 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8949 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8950 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8951 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8952 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8953 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8956 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8957 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8958 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8959 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8960 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8965 /*-----------------------------------------------------------------*/
8966 /* shiftR2Left2Result - shift right two bytes from left to result */
8967 /*-----------------------------------------------------------------*/
8968 static void shiftR2Left2Result (operand *left, int offl,
8969 operand *result, int offr,
8970 int shCount, int sign)
8972 int same = pic16_sameRegs(AOP(result), AOP(left));
8974 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8976 if (same && (offl != offr)) { // shift right bytes
8979 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8980 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8982 } else { // just treat as different later on
8994 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8999 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9000 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9002 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9003 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9004 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9005 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9010 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9013 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9014 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9021 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9022 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9023 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9025 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9026 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9027 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9028 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9030 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9031 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9032 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9034 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9035 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9036 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9037 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9038 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9042 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9043 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9047 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9048 pic16_emitpcode(POC_BTFSC,
9049 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9050 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9058 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9059 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9061 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9062 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9063 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9064 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9066 pic16_emitpcode(POC_BTFSC,
9067 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9068 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9070 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9071 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9072 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9073 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9075 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9076 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9077 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9078 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9079 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9080 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9081 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9082 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9084 pic16_emitpcode(POC_BTFSC,
9085 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9086 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9088 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9089 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9096 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9097 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9098 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9099 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9102 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9104 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9109 /*-----------------------------------------------------------------*/
9110 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9111 /*-----------------------------------------------------------------*/
9112 static void shiftLLeftOrResult (operand *left, int offl,
9113 operand *result, int offr, int shCount)
9115 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9117 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9118 /* shift left accumulator */
9120 /* or with result */
9121 /* back to result */
9122 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9125 /*-----------------------------------------------------------------*/
9126 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9127 /*-----------------------------------------------------------------*/
9128 static void shiftRLeftOrResult (operand *left, int offl,
9129 operand *result, int offr, int shCount)
9131 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9133 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9134 /* shift right accumulator */
9136 /* or with result */
9137 /* back to result */
9138 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9141 /*-----------------------------------------------------------------*/
9142 /* genlshOne - left shift a one byte quantity by known count */
9143 /*-----------------------------------------------------------------*/
9144 static void genlshOne (operand *result, operand *left, int shCount)
9146 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9147 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9150 /*-----------------------------------------------------------------*/
9151 /* genlshTwo - left shift two bytes by known amount != 0 */
9152 /*-----------------------------------------------------------------*/
9153 static void genlshTwo (operand *result,operand *left, int shCount)
9157 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9158 size = pic16_getDataSize(result);
9160 /* if shCount >= 8 */
9166 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9168 movLeft2Result(left, LSB, result, MSB16);
9170 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9173 /* 1 <= shCount <= 7 */
9176 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9178 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9182 /*-----------------------------------------------------------------*/
9183 /* shiftLLong - shift left one long from left to result */
9184 /* offr = LSB or MSB16 */
9185 /*-----------------------------------------------------------------*/
9186 static void shiftLLong (operand *left, operand *result, int offr )
9188 int size = AOP_SIZE(result);
9189 int same = pic16_sameRegs(AOP(left),AOP(result));
9192 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9194 if (same && (offr == MSB16)) { //shift one byte
9195 for(i=size-1;i>=MSB16;i--) {
9196 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9197 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9200 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9203 if (size > LSB+offr ){
9205 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9207 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9208 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9212 if(size > MSB16+offr){
9214 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9216 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9217 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9221 if(size > MSB24+offr){
9223 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9225 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9226 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9230 if(size > MSB32+offr){
9232 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9234 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9235 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9239 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9243 /*-----------------------------------------------------------------*/
9244 /* genlshFour - shift four byte by a known amount != 0 */
9245 /*-----------------------------------------------------------------*/
9246 static void genlshFour (operand *result, operand *left, int shCount)
9250 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9251 size = AOP_SIZE(result);
9253 /* if shifting more that 3 bytes */
9254 if (shCount >= 24 ) {
9257 /* lowest order of left goes to the highest
9258 order of the destination */
9259 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9261 movLeft2Result(left, LSB, result, MSB32);
9263 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9264 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9265 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9270 /* more than two bytes */
9271 else if ( shCount >= 16 ) {
9272 /* lower order two bytes goes to higher order two bytes */
9274 /* if some more remaining */
9276 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9278 movLeft2Result(left, MSB16, result, MSB32);
9279 movLeft2Result(left, LSB, result, MSB24);
9281 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9282 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9286 /* if more than 1 byte */
9287 else if ( shCount >= 8 ) {
9288 /* lower order three bytes goes to higher order three bytes */
9292 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9294 movLeft2Result(left, LSB, result, MSB16);
9296 else{ /* size = 4 */
9298 movLeft2Result(left, MSB24, result, MSB32);
9299 movLeft2Result(left, MSB16, result, MSB24);
9300 movLeft2Result(left, LSB, result, MSB16);
9301 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9303 else if(shCount == 1)
9304 shiftLLong(left, result, MSB16);
9306 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9307 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9308 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9309 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9314 /* 1 <= shCount <= 7 */
9315 else if(shCount <= 3)
9317 shiftLLong(left, result, LSB);
9318 while(--shCount >= 1)
9319 shiftLLong(result, result, LSB);
9321 /* 3 <= shCount <= 7, optimize */
9323 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9324 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9325 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9329 /*-----------------------------------------------------------------*/
9330 /* genLeftShiftLiteral - left shifting by known count */
9331 /*-----------------------------------------------------------------*/
9332 void pic16_genLeftShiftLiteral (operand *left,
9337 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9341 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9342 pic16_freeAsmop(right,NULL,ic,TRUE);
9344 pic16_aopOp(left,ic,FALSE);
9345 pic16_aopOp(result,ic,TRUE);
9347 size = getSize(operandType(result));
9350 pic16_emitcode("; shift left ","result %d, left %d",size,
9354 /* I suppose that the left size >= result size */
9357 movLeft2Result(left, size, result, size);
9361 else if(shCount >= (size * 8))
9363 pic16_aopPut(AOP(result),zero,size);
9367 genlshOne (result,left,shCount);
9372 genlshTwo (result,left,shCount);
9376 genlshFour (result,left,shCount);
9380 pic16_freeAsmop(left,NULL,ic,TRUE);
9381 pic16_freeAsmop(result,NULL,ic,TRUE);
9384 /*-----------------------------------------------------------------*
9385 * genMultiAsm - repeat assembly instruction for size of register.
9386 * if endian == 1, then the high byte (i.e base address + size of
9387 * register) is used first else the low byte is used first;
9388 *-----------------------------------------------------------------*/
9389 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9394 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9407 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9413 #if !(USE_GENERIC_SIGNED_SHIFT)
9414 /*-----------------------------------------------------------------*/
9415 /* genLeftShift - generates code for left shifting */
9416 /*-----------------------------------------------------------------*/
9417 static void genLeftShift (iCode *ic)
9419 operand *left,*right, *result;
9422 symbol *tlbl , *tlbl1;
9425 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9427 right = IC_RIGHT(ic);
9429 result = IC_RESULT(ic);
9431 pic16_aopOp(right,ic,FALSE);
9433 /* if the shift count is known then do it
9434 as efficiently as possible */
9435 if (AOP_TYPE(right) == AOP_LIT) {
9436 pic16_genLeftShiftLiteral (left,right,result,ic);
9440 /* shift count is unknown then we have to form
9441 * a loop. Get the loop count in WREG : Note: we take
9442 * only the lower order byte since shifting
9443 * more than 32 bits make no sense anyway, ( the
9444 * largest size of an object can be only 32 bits ) */
9446 pic16_aopOp(left,ic,FALSE);
9447 pic16_aopOp(result,ic,FALSE);
9449 /* now move the left to the result if they are not the
9450 * same, and if size > 1,
9451 * and if right is not same to result (!!!) -- VR */
9452 if (!pic16_sameRegs(AOP(left),AOP(result))
9453 && (AOP_SIZE(result) > 1)) {
9455 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9457 size = AOP_SIZE(result);
9462 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9463 if (*l == '@' && (IS_AOP_PREG(result))) {
9465 pic16_emitcode("mov","a,%s",l);
9466 pic16_aopPut(AOP(result),"a",offset);
9470 /* we don't know if left is a literal or a register, take care -- VR */
9471 pic16_mov2f(AOP(result), AOP(left), offset);
9477 size = AOP_SIZE(result);
9479 /* if it is only one byte then */
9481 if(optimized_for_speed) {
9482 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9483 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9484 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9485 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9486 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9487 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9488 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9489 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9490 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9491 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9492 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9493 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9496 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9498 tlbl = newiTempLabel(NULL);
9501 /* this is already done, why change it? */
9502 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9503 pic16_mov2f(AOP(result), AOP(left), 0);
9507 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9508 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9509 pic16_emitpLabel(tlbl->key);
9510 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9511 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9513 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9518 if (pic16_sameRegs(AOP(left),AOP(result))) {
9520 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9522 tlbl = newiTempLabel(NULL);
9523 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9524 genMultiAsm(POC_RRCF, result, size,1);
9525 pic16_emitpLabel(tlbl->key);
9526 genMultiAsm(POC_RLCF, result, size,0);
9527 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9529 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9533 //tlbl = newiTempLabel(NULL);
9535 //tlbl1 = newiTempLabel(NULL);
9537 //reAdjustPreg(AOP(result));
9539 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9540 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9541 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9543 //pic16_emitcode("add","a,acc");
9544 //pic16_aopPut(AOP(result),"a",offset++);
9546 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9548 // pic16_emitcode("rlc","a");
9549 // pic16_aopPut(AOP(result),"a",offset++);
9551 //reAdjustPreg(AOP(result));
9553 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9554 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9557 tlbl = newiTempLabel(NULL);
9558 tlbl1= newiTempLabel(NULL);
9560 size = AOP_SIZE(result);
9563 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9565 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9567 /* offset should be 0, 1 or 3 */
9569 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9571 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9573 pic16_emitpcode(POC_MOVWF, pctemp);
9576 pic16_emitpLabel(tlbl->key);
9579 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9581 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9583 pic16_emitpcode(POC_DECFSZ, pctemp);
9584 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9585 pic16_emitpLabel(tlbl1->key);
9587 pic16_popReleaseTempReg(pctemp,1);
9591 pic16_freeAsmop (right,NULL,ic,TRUE);
9592 pic16_freeAsmop(left,NULL,ic,TRUE);
9593 pic16_freeAsmop(result,NULL,ic,TRUE);
9599 #error old code (left here for reference)
9600 /*-----------------------------------------------------------------*/
9601 /* genLeftShift - generates code for left shifting */
9602 /*-----------------------------------------------------------------*/
9603 static void genLeftShift (iCode *ic)
9605 operand *left,*right, *result;
9608 symbol *tlbl , *tlbl1;
9611 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9613 right = IC_RIGHT(ic);
9615 result = IC_RESULT(ic);
9617 pic16_aopOp(right,ic,FALSE);
9619 /* if the shift count is known then do it
9620 as efficiently as possible */
9621 if (AOP_TYPE(right) == AOP_LIT) {
9622 pic16_genLeftShiftLiteral (left,right,result,ic);
9626 /* shift count is unknown then we have to form
9627 a loop get the loop count in B : Note: we take
9628 only the lower order byte since shifting
9629 more that 32 bits make no sense anyway, ( the
9630 largest size of an object can be only 32 bits ) */
9633 pic16_aopOp(left,ic,FALSE);
9634 pic16_aopOp(result,ic,FALSE);
9636 /* now move the left to the result if they are not the
9638 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9639 AOP_SIZE(result) > 1) {
9641 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9643 size = AOP_SIZE(result);
9646 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9647 if (*l == '@' && (IS_AOP_PREG(result))) {
9649 pic16_emitcode("mov","a,%s",l);
9650 pic16_aopPut(AOP(result),"a",offset);
9653 /* we don't know if left is a literal or a register, take care -- VR */
9654 pic16_mov2f(AOP(result), AOP(left), offset);
9660 size = AOP_SIZE(result);
9662 /* if it is only one byte then */
9664 if(optimized_for_speed) {
9665 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9666 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9667 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9668 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9669 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9670 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9671 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9672 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9673 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9674 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9675 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9676 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9679 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9681 tlbl = newiTempLabel(NULL);
9682 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9683 pic16_mov2f(AOP(result), AOP(left), 0);
9685 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9686 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9689 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9690 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9691 pic16_emitpLabel(tlbl->key);
9692 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9693 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9695 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9700 if (pic16_sameRegs(AOP(left),AOP(result))) {
9702 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9704 tlbl = newiTempLabel(NULL);
9705 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9706 genMultiAsm(POC_RRCF, result, size,1);
9707 pic16_emitpLabel(tlbl->key);
9708 genMultiAsm(POC_RLCF, result, size,0);
9709 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9711 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9715 //tlbl = newiTempLabel(NULL);
9717 //tlbl1 = newiTempLabel(NULL);
9719 //reAdjustPreg(AOP(result));
9721 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9722 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9723 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9725 //pic16_emitcode("add","a,acc");
9726 //pic16_aopPut(AOP(result),"a",offset++);
9728 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9730 // pic16_emitcode("rlc","a");
9731 // pic16_aopPut(AOP(result),"a",offset++);
9733 //reAdjustPreg(AOP(result));
9735 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9736 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9739 tlbl = newiTempLabel(NULL);
9740 tlbl1= newiTempLabel(NULL);
9742 size = AOP_SIZE(result);
9745 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9747 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9749 /* offset should be 0, 1 or 3 */
9751 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9753 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9755 pic16_emitpcode(POC_MOVWF, pctemp);
9758 pic16_emitpLabel(tlbl->key);
9761 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9763 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9765 pic16_emitpcode(POC_DECFSZ, pctemp);
9766 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9767 pic16_emitpLabel(tlbl1->key);
9769 pic16_popReleaseTempReg(pctemp,1);
9773 pic16_freeAsmop (right,NULL,ic,TRUE);
9774 pic16_freeAsmop(left,NULL,ic,TRUE);
9775 pic16_freeAsmop(result,NULL,ic,TRUE);
9779 /*-----------------------------------------------------------------*/
9780 /* genrshOne - right shift a one byte quantity by known count */
9781 /*-----------------------------------------------------------------*/
9782 static void genrshOne (operand *result, operand *left,
9783 int shCount, int sign)
9785 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9786 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9789 /*-----------------------------------------------------------------*/
9790 /* genrshTwo - right shift two bytes by known amount != 0 */
9791 /*-----------------------------------------------------------------*/
9792 static void genrshTwo (operand *result,operand *left,
9793 int shCount, int sign)
9795 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9796 /* if shCount >= 8 */
9800 shiftR1Left2Result(left, MSB16, result, LSB,
9803 movLeft2Result(left, MSB16, result, LSB);
9805 pic16_addSign (result, 1, sign);
9808 /* 1 <= shCount <= 7 */
9810 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9813 /*-----------------------------------------------------------------*/
9814 /* shiftRLong - shift right one long from left to result */
9815 /* offl = LSB or MSB16 */
9816 /*-----------------------------------------------------------------*/
9817 static void shiftRLong (operand *left, int offl,
9818 operand *result, int sign)
9820 int size = AOP_SIZE(result);
9821 int same = pic16_sameRegs(AOP(left),AOP(result));
9823 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9825 if (same && (offl == MSB16)) { //shift one byte right
9826 for(i=MSB16;i<size;i++) {
9827 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9828 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9833 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9839 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9841 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9842 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9846 /* add sign of "a" */
9847 pic16_addSign(result, MSB32, sign);
9851 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9853 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9854 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9858 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9860 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9861 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9865 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9868 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9869 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9874 /*-----------------------------------------------------------------*/
9875 /* genrshFour - shift four byte by a known amount != 0 */
9876 /*-----------------------------------------------------------------*/
9877 static void genrshFour (operand *result, operand *left,
9878 int shCount, int sign)
9880 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9881 /* if shifting more that 3 bytes */
9882 if(shCount >= 24 ) {
9885 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9887 movLeft2Result(left, MSB32, result, LSB);
9889 pic16_addSign(result, MSB16, sign);
9891 else if(shCount >= 16){
9894 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9896 movLeft2Result(left, MSB24, result, LSB);
9897 movLeft2Result(left, MSB32, result, MSB16);
9899 pic16_addSign(result, MSB24, sign);
9901 else if(shCount >= 8){
9904 shiftRLong(left, MSB16, result, sign);
9905 else if(shCount == 0){
9906 movLeft2Result(left, MSB16, result, LSB);
9907 movLeft2Result(left, MSB24, result, MSB16);
9908 movLeft2Result(left, MSB32, result, MSB24);
9909 pic16_addSign(result, MSB32, sign);
9911 else{ //shcount >= 2
9912 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9913 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9914 /* the last shift is signed */
9915 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9916 pic16_addSign(result, MSB32, sign);
9919 else{ /* 1 <= shCount <= 7 */
9921 shiftRLong(left, LSB, result, sign);
9923 shiftRLong(result, LSB, result, sign);
9926 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9927 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9928 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9933 /*-----------------------------------------------------------------*/
9934 /* genRightShiftLiteral - right shifting by known count */
9935 /*-----------------------------------------------------------------*/
9936 static void genRightShiftLiteral (operand *left,
9942 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9945 pic16_freeAsmop(right,NULL,ic,TRUE);
9947 pic16_aopOp(left,ic,FALSE);
9948 pic16_aopOp(result,ic,TRUE);
9950 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9953 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9957 lsize = pic16_getDataSize(left);
9958 res_size = pic16_getDataSize(result);
9959 /* test the LEFT size !!! */
9961 /* I suppose that the left size >= result size */
9963 assert (res_size <= lsize);
9964 while (res_size--) {
9965 pic16_mov2f (AOP(result), AOP(left), res_size);
9969 else if(shCount >= (lsize * 8)){
9972 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9974 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9975 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
9980 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9981 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9982 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9984 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9989 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9996 genrshOne (result,left,shCount,sign);
10000 genrshTwo (result,left,shCount,sign);
10004 genrshFour (result,left,shCount,sign);
10012 pic16_freeAsmop(left,NULL,ic,TRUE);
10013 pic16_freeAsmop(result,NULL,ic,TRUE);
10016 #if !(USE_GENERIC_SIGNED_SHIFT)
10017 /*-----------------------------------------------------------------*/
10018 /* genSignedRightShift - right shift of signed number */
10019 /*-----------------------------------------------------------------*/
10020 static void genSignedRightShift (iCode *ic)
10022 operand *right, *left, *result;
10025 symbol *tlbl, *tlbl1 ;
10028 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10030 /* we do it the hard way put the shift count in b
10031 and loop thru preserving the sign */
10032 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10034 right = IC_RIGHT(ic);
10035 left = IC_LEFT(ic);
10036 result = IC_RESULT(ic);
10038 pic16_aopOp(right,ic,FALSE);
10039 pic16_aopOp(left,ic,FALSE);
10040 pic16_aopOp(result,ic,FALSE);
10043 if ( AOP_TYPE(right) == AOP_LIT) {
10044 genRightShiftLiteral (left,right,result,ic,1);
10047 /* shift count is unknown then we have to form
10048 a loop get the loop count in B : Note: we take
10049 only the lower order byte since shifting
10050 more that 32 bits make no sense anyway, ( the
10051 largest size of an object can be only 32 bits ) */
10053 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10054 //pic16_emitcode("inc","b");
10055 //pic16_freeAsmop (right,NULL,ic,TRUE);
10056 //pic16_aopOp(left,ic,FALSE);
10057 //pic16_aopOp(result,ic,FALSE);
10059 /* now move the left to the result if they are not the
10061 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10062 AOP_SIZE(result) > 1) {
10064 size = AOP_SIZE(result);
10068 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10069 if (*l == '@' && IS_AOP_PREG(result)) {
10071 pic16_emitcode("mov","a,%s",l);
10072 pic16_aopPut(AOP(result),"a",offset);
10074 pic16_aopPut(AOP(result),l,offset);
10076 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10077 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10083 /* mov the highest order bit to OVR */
10084 tlbl = newiTempLabel(NULL);
10085 tlbl1= newiTempLabel(NULL);
10087 size = AOP_SIZE(result);
10090 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10092 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10094 /* offset should be 0, 1 or 3 */
10095 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10097 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10099 pic16_emitpcode(POC_MOVWF, pctemp);
10102 pic16_emitpLabel(tlbl->key);
10104 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10105 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10108 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10111 pic16_emitpcode(POC_DECFSZ, pctemp);
10112 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10113 pic16_emitpLabel(tlbl1->key);
10115 pic16_popReleaseTempReg(pctemp,1);
10117 size = AOP_SIZE(result);
10119 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10120 pic16_emitcode("rlc","a");
10121 pic16_emitcode("mov","ov,c");
10122 /* if it is only one byte then */
10124 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10126 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10127 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10128 pic16_emitcode("mov","c,ov");
10129 pic16_emitcode("rrc","a");
10130 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10131 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10132 pic16_aopPut(AOP(result),"a",0);
10136 reAdjustPreg(AOP(result));
10137 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10138 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10139 pic16_emitcode("mov","c,ov");
10141 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10143 pic16_emitcode("rrc","a");
10144 pic16_aopPut(AOP(result),"a",offset--);
10146 reAdjustPreg(AOP(result));
10147 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10148 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10153 pic16_freeAsmop(left,NULL,ic,TRUE);
10154 pic16_freeAsmop(result,NULL,ic,TRUE);
10155 pic16_freeAsmop(right,NULL,ic,TRUE);
10159 #if !(USE_GENERIC_SIGNED_SHIFT)
10160 #warning This implementation of genRightShift() is incomplete!
10161 /*-----------------------------------------------------------------*/
10162 /* genRightShift - generate code for right shifting */
10163 /*-----------------------------------------------------------------*/
10164 static void genRightShift (iCode *ic)
10166 operand *right, *left, *result;
10170 symbol *tlbl, *tlbl1 ;
10172 /* if signed then we do it the hard way preserve the
10173 sign bit moving it inwards */
10174 letype = getSpec(operandType(IC_LEFT(ic)));
10175 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10177 if (!SPEC_USIGN(letype)) {
10178 genSignedRightShift (ic);
10182 /* signed & unsigned types are treated the same : i.e. the
10183 signed is NOT propagated inwards : quoting from the
10184 ANSI - standard : "for E1 >> E2, is equivalent to division
10185 by 2**E2 if unsigned or if it has a non-negative value,
10186 otherwise the result is implementation defined ", MY definition
10187 is that the sign does not get propagated */
10189 right = IC_RIGHT(ic);
10190 left = IC_LEFT(ic);
10191 result = IC_RESULT(ic);
10193 pic16_aopOp(right,ic,FALSE);
10195 /* if the shift count is known then do it
10196 as efficiently as possible */
10197 if (AOP_TYPE(right) == AOP_LIT) {
10198 genRightShiftLiteral (left,right,result,ic, 0);
10202 /* shift count is unknown then we have to form
10203 a loop get the loop count in B : Note: we take
10204 only the lower order byte since shifting
10205 more that 32 bits make no sense anyway, ( the
10206 largest size of an object can be only 32 bits ) */
10208 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10209 pic16_emitcode("inc","b");
10210 pic16_aopOp(left,ic,FALSE);
10211 pic16_aopOp(result,ic,FALSE);
10213 /* now move the left to the result if they are not the
10215 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10216 AOP_SIZE(result) > 1) {
10218 size = AOP_SIZE(result);
10221 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10222 if (*l == '@' && IS_AOP_PREG(result)) {
10224 pic16_emitcode("mov","a,%s",l);
10225 pic16_aopPut(AOP(result),"a",offset);
10227 pic16_aopPut(AOP(result),l,offset);
10232 tlbl = newiTempLabel(NULL);
10233 tlbl1= newiTempLabel(NULL);
10234 size = AOP_SIZE(result);
10237 /* if it is only one byte then */
10240 tlbl = newiTempLabel(NULL);
10241 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10242 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10243 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10246 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10247 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10248 pic16_emitpLabel(tlbl->key);
10249 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10250 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10252 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10257 reAdjustPreg(AOP(result));
10258 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10259 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10262 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10264 pic16_emitcode("rrc","a");
10265 pic16_aopPut(AOP(result),"a",offset--);
10267 reAdjustPreg(AOP(result));
10269 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10270 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10273 pic16_freeAsmop(left,NULL,ic,TRUE);
10274 pic16_freeAsmop (right,NULL,ic,TRUE);
10275 pic16_freeAsmop(result,NULL,ic,TRUE);
10279 #if (USE_GENERIC_SIGNED_SHIFT)
10280 /*-----------------------------------------------------------------*/
10281 /* genGenericShift - generates code for left or right shifting */
10282 /*-----------------------------------------------------------------*/
10283 static void genGenericShift (iCode *ic, int isShiftLeft) {
10284 operand *left,*right, *result;
10286 int sign, signedCount;
10287 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10288 PIC_OPCODE pos_shift, neg_shift;
10292 right = IC_RIGHT(ic);
10293 left = IC_LEFT(ic);
10294 result = IC_RESULT(ic);
10296 pic16_aopOp(right,ic,FALSE);
10297 pic16_aopOp(left,ic,FALSE);
10298 pic16_aopOp(result,ic,TRUE);
10300 sign = !SPEC_USIGN(operandType (left));
10301 signedCount = !SPEC_USIGN(operandType (right));
10303 /* if the shift count is known then do it
10304 as efficiently as possible */
10305 if (AOP_TYPE(right) == AOP_LIT) {
10306 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10307 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10308 // we should modify right->aopu.aop_lit here!
10309 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10310 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10312 pic16_genLeftShiftLiteral (left,right,result,ic);
10314 genRightShiftLiteral (left,right,result,ic, sign);
10317 } // if (right is literal)
10319 /* shift count is unknown then we have to form a loop.
10320 * Note: we take only the lower order byte since shifting
10321 * more than 32 bits make no sense anyway, ( the
10322 * largest size of an object can be only 32 bits )
10323 * Note: we perform arithmetic shifts if the left operand is
10324 * signed and we do an (effective) right shift, i. e. we
10325 * shift in the sign bit from the left. */
10327 label_complete = newiTempLabel ( NULL );
10328 label_loop_pos = newiTempLabel ( NULL );
10329 label_loop_neg = NULL;
10330 label_negative = NULL;
10331 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10332 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10335 // additional labels needed
10336 label_loop_neg = newiTempLabel ( NULL );
10337 label_negative = newiTempLabel ( NULL );
10340 // copy source to result -- this will effectively truncate the left operand to the size of result!
10341 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10342 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10343 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10344 pic16_mov2f (AOP(result),AOP(left), offset);
10347 // if result is longer than left, fill with zeros (or sign)
10348 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10349 if (sign && AOP_SIZE(left) > 0) {
10350 // shift signed operand -- fill with sign
10351 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10352 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10353 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10354 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10355 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10358 // shift unsigned operand -- fill result with zeros
10359 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10360 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10363 } // if (size mismatch)
10365 pic16_mov2w (AOP(right), 0);
10366 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10367 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10370 // perform a shift by one (shift count is positive)
10371 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10372 // 2n+[2,3]+({1,3}+n+3)c-2+[0,2]=({4,6}+n)c+2n+[0,3] ({5,7}c+[2,5] / {6,8}c+[4, 7] / {8,10}c+[ 8,11])
10373 pic16_emitpLabel (label_loop_pos->key);
10375 if (sign && (pos_shift == POC_RRCF)) {
10376 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10379 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10380 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10381 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10383 // perform a shift by one (shift count is positive)
10384 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10385 // 2n+[2,3]+2+({0,2}+n+3)c-1+[0,2]=({3,5}+n)c+2n+[3,6] ({4,6}c+[5,8] / {5,7}c+[7,10] / {7, 9}c+[11,14])
10386 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10387 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10389 pic16_emitpLabel (label_loop_pos->key);
10390 if (sign && (pos_shift == POC_RRCF)) {
10391 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10394 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10395 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10396 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10397 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10401 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10403 pic16_emitpLabel (label_negative->key);
10404 // perform a shift by -1 (shift count is negative)
10405 // 2n+4+1+({0,2}+n+3)*c-1=({3,5}+n)c+2n+4 ({4,6}c+6 / {5,7}c+8 / {7,9}c+12)
10407 pic16_emitpLabel (label_loop_neg->key);
10408 if (sign && (neg_shift == POC_RRCF)) {
10409 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10412 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10413 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10414 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10415 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10416 } // if (signedCount)
10418 pic16_emitpLabel (label_complete->key);
10421 pic16_freeAsmop (right,NULL,ic,TRUE);
10422 pic16_freeAsmop(left,NULL,ic,TRUE);
10423 pic16_freeAsmop(result,NULL,ic,TRUE);
10426 static void genLeftShift (iCode *ic) {
10427 genGenericShift (ic, 1);
10430 static void genRightShift (iCode *ic) {
10431 genGenericShift (ic, 0);
10436 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10437 void pic16_loadFSR0(operand *op, int lit)
10439 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10440 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10442 assert (!OP_SYMBOL(op)->remat);
10443 // set up FSR0 with address of result
10444 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10445 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10449 /*----------------------------------------------------------------*/
10450 /* pic16_derefPtr - move one byte from the location ptr points to */
10451 /* to WREG (doWrite == 0) or one byte from WREG */
10452 /* to the location ptr points to (doWrite != 0) */
10453 /*----------------------------------------------------------------*/
10454 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10456 if (!IS_PTR(operandType(ptr)))
10458 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10459 else pic16_mov2w (AOP(ptr), 0);
10463 //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10464 /* We might determine pointer type right here: */
10465 p_type = DCL_TYPE(operandType(ptr));
10470 if (!fsr0_setup || !*fsr0_setup)
10472 pic16_loadFSR0( ptr, 0 );
10473 if (fsr0_setup) *fsr0_setup = 1;
10476 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10478 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10482 if (AOP(ptr)->aopu.aop_reg[2]) {
10483 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10484 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10485 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10486 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl)));
10487 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(ptr),2));
10488 pic16_callGenericPointerRW(doWrite, 1);
10490 // data pointer (just 2 byte given)
10491 if (!fsr0_setup || !*fsr0_setup)
10493 pic16_loadFSR0( ptr, 0 );
10494 if (fsr0_setup) *fsr0_setup = 1;
10497 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10499 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10504 assert (0 && "invalid pointer type specified");
10509 /*-----------------------------------------------------------------*/
10510 /* genUnpackBits - generates code for unpacking bits */
10511 /*-----------------------------------------------------------------*/
10512 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10515 sym_link *etype, *letype;
10516 int blen=0, bstr=0;
10521 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10522 etype = getSpec(operandType(result));
10523 letype = getSpec(operandType(left));
10525 // if(IS_BITFIELD(etype)) {
10526 blen = SPEC_BLEN(etype);
10527 bstr = SPEC_BSTR(etype);
10530 lbstr = SPEC_BSTR( letype );
10532 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10533 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10536 if((blen == 1) && (bstr < 8)
10537 && (!IS_PTR(operandType(left)) || PIC_IS_DATA_PTR(operandType(left)))) {
10538 /* it is a single bit, so use the appropriate bit instructions */
10539 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10541 same = pic16_sameRegs(AOP(left),AOP(result));
10542 op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10543 pic16_emitpcode(POC_CLRF, op);
10545 if(!IS_PTR(operandType(left))) {
10546 /* workaround to reduce the extra lfsr instruction */
10547 pic16_emitpcode(POC_BTFSC,
10548 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10550 assert (PIC_IS_DATA_PTR (operandType(left)));
10551 pic16_loadFSR0 (left, 0);
10552 pic16_emitpcode(POC_BTFSC,
10553 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10556 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10557 /* unsigned bitfields result in either 0 or 1 */
10558 pic16_emitpcode(POC_INCF, op);
10560 /* signed bitfields result in either 0 or -1 */
10561 pic16_emitpcode(POC_DECF, op);
10564 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10567 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10573 if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
10574 // access symbol directly
10575 pic16_mov2w (AOP(left), 0);
10577 pic16_derefPtr (left, ptype, 0, NULL);
10580 /* if we have bitdisplacement then it fits */
10581 /* into this byte completely or if length is */
10582 /* less than a byte */
10583 if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) {
10585 /* shift right acc */
10588 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10589 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10591 /* VR -- normally I would use the following, but since we use the hack,
10592 * to avoid the masking from AccRsh, why not mask it right now? */
10595 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10598 /* extend signed bitfields to 8 bits */
10599 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10601 assert (blen + bstr > 0);
10602 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10603 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10606 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10608 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10612 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10613 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10620 static void genDataPointerGet(operand *left,
10624 int size, offset = 0, leoffset=0 ;
10626 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10627 pic16_aopOp(result, ic, TRUE);
10631 size = AOP_SIZE(result);
10632 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10636 /* The following tests may save a redudant movff instruction when
10637 * accessing unions */
10639 /* if they are the same */
10640 if (operandsEqu (left, result)) {
10641 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10647 /* if they are the same registers */
10648 if (pic16_sameRegs(AOP(left),AOP(result))) {
10649 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10655 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10656 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10657 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10664 if ( AOP_TYPE(left) == AOP_PCODE) {
10665 fprintf(stderr,"genDataPointerGet %s, %d\n",
10666 AOP(left)->aopu.pcop->name,
10667 (AOP(left)->aopu.pcop->type == PO_DIR)?
10668 PCOR(AOP(left)->aopu.pcop)->instance:
10669 PCOI(AOP(left)->aopu.pcop)->offset);
10673 if(AOP(left)->aopu.pcop->type == PO_DIR)
10674 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10676 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10679 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10681 // pic16_DumpOp("(result)",result);
10682 if(is_LitAOp(AOP(result))) {
10683 pic16_mov2w(AOP(left), offset); // patch 8
10684 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10686 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10687 pic16_popGet(AOP(left), offset), //patch 8
10688 pic16_popGet(AOP(result), offset)));
10696 pic16_freeAsmop(result,NULL,ic,TRUE);
10701 /*-----------------------------------------------------------------*/
10702 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10703 /*-----------------------------------------------------------------*/
10704 static void genNearPointerGet (operand *left,
10708 // asmop *aop = NULL;
10709 //regs *preg = NULL ;
10710 sym_link *rtype, *retype;
10711 sym_link *ltype, *letype;
10715 rtype = operandType(result);
10716 retype= getSpec(rtype);
10717 ltype = operandType(left);
10718 letype= getSpec(ltype);
10720 pic16_aopOp(left,ic,FALSE);
10722 // pic16_DumpOp("(left)",left);
10723 // pic16_DumpOp("(result)",result);
10725 /* if left is rematerialisable and
10726 * result is not bit variable type and
10727 * the left is pointer to data space i.e
10728 * lower 128 bytes of space */
10730 if (AOP_TYPE(left) == AOP_PCODE
10731 && !IS_BITFIELD(retype)
10732 && DCL_TYPE(ltype) == POINTER) {
10734 genDataPointerGet (left,result,ic);
10735 pic16_freeAsmop(left, NULL, ic, TRUE);
10739 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10740 pic16_aopOp (result,ic,TRUE);
10742 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10745 if(IS_BITFIELD( retype )
10746 && (SPEC_BLEN(operandType(result))==1)
10750 int bitstrt, bytestrt;
10752 /* if this is bitfield of size 1, see if we are checking the value
10753 * of a single bit in an if-statement,
10754 * if yes, then don't generate usual code, but execute the
10755 * genIfx directly -- VR */
10759 /* CHECK: if next iCode is IFX
10760 * and current result operand is nextic's conditional operand
10761 * and current result operand live ranges ends at nextic's key number
10763 if((nextic->op == IFX)
10764 && (result == IC_COND(nextic))
10765 && (OP_LIVETO(result) == nextic->seq)
10766 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10768 /* everything is ok then */
10769 /* find a way to optimize the genIfx iCode */
10771 bytestrt = SPEC_BSTR(operandType(result))/8;
10772 bitstrt = SPEC_BSTR(operandType(result))%8;
10774 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10776 genIfxpCOpJump(nextic, jop);
10778 pic16_freeAsmop(left, NULL, ic, TRUE);
10779 pic16_freeAsmop(result, NULL, ic, TRUE);
10785 /* if bitfield then unpack the bits */
10786 if (IS_BITFIELD(letype))
10787 genUnpackBits (result, left, NULL, POINTER);
10789 /* we have can just get the values */
10790 int size = AOP_SIZE(result);
10793 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10795 pic16_loadFSR0( left, 0 );
10799 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10800 pic16_popGet(AOP(result), offset++)));
10802 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10803 pic16_popGet(AOP(result), offset++)));
10809 /* now some housekeeping stuff */
10811 /* we had to allocate for this iCode */
10812 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10813 pic16_freeAsmop(NULL,aop,ic,TRUE);
10815 /* we did not allocate which means left
10816 * already in a pointer register, then
10817 * if size > 0 && this could be used again
10818 * we have to point it back to where it
10820 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10821 if (AOP_SIZE(result) > 1
10822 && !OP_SYMBOL(left)->remat
10823 && ( OP_SYMBOL(left)->liveTo > ic->seq
10825 // int size = AOP_SIZE(result) - 1;
10827 // pic16_emitcode("dec","%s",rname);
10833 pic16_freeAsmop(left,NULL,ic,TRUE);
10834 pic16_freeAsmop(result,NULL,ic,TRUE);
10837 /*-----------------------------------------------------------------*/
10838 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10839 /*-----------------------------------------------------------------*/
10840 static void genPagedPointerGet (operand *left,
10845 regs *preg = NULL ;
10847 sym_link *rtype, *retype;
10849 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10851 rtype = operandType(result);
10852 retype= getSpec(rtype);
10854 pic16_aopOp(left,ic,FALSE);
10856 /* if the value is already in a pointer register
10857 then don't need anything more */
10858 if (!AOP_INPREG(AOP(left))) {
10859 /* otherwise get a free pointer register */
10861 preg = getFreePtr(ic,&aop,FALSE);
10862 pic16_emitcode("mov","%s,%s",
10864 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10865 rname = preg->name ;
10867 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10869 pic16_freeAsmop(left,NULL,ic,TRUE);
10870 pic16_aopOp (result,ic,TRUE);
10872 /* if bitfield then unpack the bits */
10873 if (IS_BITFIELD(retype))
10874 genUnpackBits (result,left,rname,PPOINTER);
10876 /* we have can just get the values */
10877 int size = AOP_SIZE(result);
10882 pic16_emitcode("movx","a,@%s",rname);
10883 pic16_aopPut(AOP(result),"a",offset);
10888 pic16_emitcode("inc","%s",rname);
10892 /* now some housekeeping stuff */
10894 /* we had to allocate for this iCode */
10895 pic16_freeAsmop(NULL,aop,ic,TRUE);
10897 /* we did not allocate which means left
10898 already in a pointer register, then
10899 if size > 0 && this could be used again
10900 we have to point it back to where it
10902 if (AOP_SIZE(result) > 1 &&
10903 !OP_SYMBOL(left)->remat &&
10904 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10906 int size = AOP_SIZE(result) - 1;
10908 pic16_emitcode("dec","%s",rname);
10913 pic16_freeAsmop(result,NULL,ic,TRUE);
10919 /* This code is not adjusted to PIC16 and fails utterly.
10920 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10922 /*-----------------------------------------------------------------*/
10923 /* genFarPointerGet - gget value from far space */
10924 /*-----------------------------------------------------------------*/
10925 static void genFarPointerGet (operand *left,
10926 operand *result, iCode *ic)
10929 sym_link *retype = getSpec(operandType(result));
10931 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10933 pic16_aopOp(left,ic,FALSE);
10935 /* if the operand is already in dptr
10936 then we do nothing else we move the value to dptr */
10937 if (AOP_TYPE(left) != AOP_STR) {
10938 /* if this is remateriazable */
10939 if (AOP_TYPE(left) == AOP_IMMD)
10940 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10941 else { /* we need to get it byte by byte */
10942 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10943 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10944 if (options.model == MODEL_FLAT24)
10946 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10950 /* so dptr know contains the address */
10951 pic16_freeAsmop(left,NULL,ic,TRUE);
10952 pic16_aopOp(result,ic,TRUE);
10954 /* if bit then unpack */
10955 if (IS_BITFIELD(retype))
10956 genUnpackBits(result,left,"dptr",FPOINTER);
10958 size = AOP_SIZE(result);
10962 pic16_emitcode("movx","a,@dptr");
10963 pic16_aopPut(AOP(result),"a",offset++);
10965 pic16_emitcode("inc","dptr");
10969 pic16_freeAsmop(result,NULL,ic,TRUE);
10974 /*-----------------------------------------------------------------*/
10975 /* genCodePointerGet - get value from code space */
10976 /*-----------------------------------------------------------------*/
10977 static void genCodePointerGet (operand *left,
10978 operand *result, iCode *ic)
10981 sym_link *retype = getSpec(operandType(result));
10983 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10985 pic16_aopOp(left,ic,FALSE);
10987 /* if the operand is already in dptr
10988 then we do nothing else we move the value to dptr */
10989 if (AOP_TYPE(left) != AOP_STR) {
10990 /* if this is remateriazable */
10991 if (AOP_TYPE(left) == AOP_IMMD)
10992 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10993 else { /* we need to get it byte by byte */
10994 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10995 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10996 if (options.model == MODEL_FLAT24)
10998 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11002 /* so dptr know contains the address */
11003 pic16_freeAsmop(left,NULL,ic,TRUE);
11004 pic16_aopOp(result,ic,FALSE);
11006 /* if bit then unpack */
11007 if (IS_BITFIELD(retype))
11008 genUnpackBits(result,left,"dptr",CPOINTER);
11010 size = AOP_SIZE(result);
11014 pic16_emitcode("clr","a");
11015 pic16_emitcode("movc","a,@a+dptr");
11016 pic16_aopPut(AOP(result),"a",offset++);
11018 pic16_emitcode("inc","dptr");
11022 pic16_freeAsmop(result,NULL,ic,TRUE);
11027 /*-----------------------------------------------------------------*/
11028 /* genGenPointerGet - gget value from generic pointer space */
11029 /*-----------------------------------------------------------------*/
11030 static void genGenPointerGet (operand *left,
11031 operand *result, iCode *ic)
11033 int size, offset, lit;
11034 sym_link *retype = getSpec(operandType(result));
11036 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11037 pic16_aopOp(left,ic,FALSE);
11038 pic16_aopOp(result,ic,FALSE);
11039 size = AOP_SIZE(result);
11041 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11043 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11045 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11046 // load FSR0 from immediate
11047 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11049 // pic16_loadFSR0( left );
11054 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11056 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11063 else { /* we need to get it byte by byte */
11064 // set up FSR0 with address from left
11065 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11066 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11072 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11074 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11081 /* if bit then unpack */
11082 if (IS_BITFIELD(retype))
11083 genUnpackBits(result,left,"BAD",GPOINTER);
11086 pic16_freeAsmop(left,NULL,ic,TRUE);
11087 pic16_freeAsmop(result,NULL,ic,TRUE);
11093 /*-----------------------------------------------------------------*/
11094 /* genGenPointerGet - gget value from generic pointer space */
11095 /*-----------------------------------------------------------------*/
11096 static void genGenPointerGet (operand *left,
11097 operand *result, iCode *ic)
11099 int size, offset, lit;
11100 sym_link *letype = getSpec(operandType(left));
11102 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11103 pic16_aopOp(left,ic,FALSE);
11104 pic16_aopOp(result,ic,TRUE);
11105 size = AOP_SIZE(result);
11107 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11109 /* if bit then unpack */
11110 if (IS_BITFIELD(letype)) {
11111 genUnpackBits(result,left,"BAD",GPOINTER);
11115 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11117 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11118 // load FSR0 from immediate
11119 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11121 werror(W_POSSBUG2, __FILE__, __LINE__);
11126 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11128 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11135 } else { /* we need to get it byte by byte */
11137 /* set up WREG:PRODL:FSR0L with address from left */
11138 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11139 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11140 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11142 pic16_callGenericPointerRW(0, size);
11144 assignResultValue(result, 1);
11150 pic16_freeAsmop(left,NULL,ic,TRUE);
11151 pic16_freeAsmop(result,NULL,ic,TRUE);
11154 /*-----------------------------------------------------------------*/
11155 /* genConstPointerGet - get value from const generic pointer space */
11156 /*-----------------------------------------------------------------*/
11157 static void genConstPointerGet (operand *left,
11158 operand *result, iCode *ic)
11160 //sym_link *retype = getSpec(operandType(result));
11161 // symbol *albl = newiTempLabel(NULL); // patch 15
11162 // symbol *blbl = newiTempLabel(NULL); //
11163 // PIC_OPCODE poc; // patch 15
11167 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11168 pic16_aopOp(left,ic,FALSE);
11169 pic16_aopOp(result,ic,TRUE);
11170 size = AOP_SIZE(result);
11172 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11174 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11176 // set up table pointer
11177 if( (AOP_TYPE(left) == AOP_PCODE)
11178 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11179 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11181 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11182 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11183 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11184 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11185 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11186 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11188 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11189 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11190 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11194 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11195 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11199 pic16_freeAsmop(left,NULL,ic,TRUE);
11200 pic16_freeAsmop(result,NULL,ic,TRUE);
11204 /*-----------------------------------------------------------------*/
11205 /* genPointerGet - generate code for pointer get */
11206 /*-----------------------------------------------------------------*/
11207 static void genPointerGet (iCode *ic)
11209 operand *left, *result ;
11210 sym_link *type, *etype;
11215 left = IC_LEFT(ic);
11216 result = IC_RESULT(ic) ;
11218 /* depending on the type of pointer we need to
11219 move it to the correct pointer register */
11220 type = operandType(left);
11221 etype = getSpec(type);
11224 if (IS_PTR_CONST(type))
11226 if (IS_CODEPTR(type))
11228 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11230 /* if left is of type of pointer then it is simple */
11231 if (IS_PTR(type) && !IS_FUNC(type->next))
11232 p_type = DCL_TYPE(type);
11234 /* we have to go by the storage class */
11235 p_type = PTR_TYPE(SPEC_OCLS(etype));
11237 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11239 if (SPEC_OCLS(etype)->codesp ) {
11240 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11241 //p_type = CPOINTER ;
11243 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11244 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11245 /*p_type = FPOINTER ;*/
11247 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11248 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11249 /* p_type = PPOINTER; */
11251 if (SPEC_OCLS(etype) == idata ) {
11252 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11253 /* p_type = IPOINTER; */
11255 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11256 /* p_type = POINTER ; */
11260 /* now that we have the pointer type we assign
11261 the pointer values */
11266 genNearPointerGet (left,result,ic);
11270 genPagedPointerGet(left,result,ic);
11274 /* PICs do not support FAR pointers... */
11275 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11277 genFarPointerGet (left,result,ic);
11282 genConstPointerGet (left,result,ic);
11283 //pic16_emitcodePointerGet (left,result,ic);
11288 if (IS_PTR_CONST(type))
11289 genConstPointerGet (left,result,ic);
11292 genGenPointerGet (left,result,ic);
11296 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11297 "genPointerGet: illegal pointer type");
11302 /*-----------------------------------------------------------------*/
11303 /* genPackBits - generates code for packed bit storage */
11304 /*-----------------------------------------------------------------*/
11305 static void genPackBits (sym_link *etype , operand *result,
11307 char *rname, int p_type)
11315 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11316 blen = SPEC_BLEN(etype);
11317 bstr = SPEC_BSTR(etype);
11319 retype = getSpec(operandType(right));
11321 if(AOP_TYPE(right) == AOP_LIT) {
11322 if((blen == 1) && (bstr < 8)) {
11324 /* it is a single bit, so use the appropriate bit instructions */
11326 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11328 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11329 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11330 if(!IS_PTR(operandType(result))) {
11331 /* workaround to reduce the extra lfsr instruction */
11333 pic16_emitpcode(POC_BSF,
11334 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11336 pic16_emitpcode(POC_BCF,
11337 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11340 if (PIC_IS_DATA_PTR(operandType(result))) {
11341 pic16_loadFSR0(result, 0);
11342 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11343 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11345 /* get old value */
11346 pic16_derefPtr (result, p_type, 0, NULL);
11347 pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11348 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11349 /* write back new value */
11350 pic16_derefPtr (result, p_type, 1, NULL);
11356 /* move literal to W */
11357 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11360 if(IS_BITFIELD(retype)
11361 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11365 rblen = SPEC_BLEN( retype );
11366 rbstr = SPEC_BSTR( retype );
11369 if(IS_BITFIELD(etype)) {
11370 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11371 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11373 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11376 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11378 if(IS_BITFIELD(etype)) {
11379 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11381 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11384 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11388 /* move right to W */
11389 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11392 /* if the bit length is less than or */
11393 /* it exactly fits a byte then */
11394 if((shCnt=SPEC_BSTR(etype))
11395 || SPEC_BLEN(etype) <= 8 ) {
11396 int fsr0_setup = 0;
11398 if (blen != 8 || bstr != 0) {
11399 // we need to combine the value with the old value
11400 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11402 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11403 SPEC_BSTR(etype), SPEC_BLEN(etype));
11405 /* shift left acc */
11408 /* using PRODH as a temporary register here */
11409 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11411 if (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) {
11412 /* access symbol directly */
11413 pic16_mov2w (AOP(result), 0);
11415 /* get old value */
11416 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11419 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11420 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11421 (unsigned char)(0xff >> (8-bstr))) ));
11422 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11423 } // if (blen != 8 || bstr != 0)
11425 /* write new value back */
11426 if (IS_SYMOP(result) & !IS_PTR(operandType(result))) {
11427 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11429 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11438 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11439 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11444 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11445 rLen = SPEC_BLEN(etype)-8;
11447 /* now generate for lengths greater than one byte */
11451 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11457 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11463 pic16_emitcode("movx","@dptr,a");
11468 DEBUGpic16_emitcode(";lcall","__gptrput");
11476 pic16_mov2w(AOP(right), offset++);
11479 /* last last was not complete */
11481 /* save the byte & read byte */
11484 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11485 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11490 pic16_emitcode ("mov","b,a");
11491 pic16_emitcode("movx","a,@dptr");
11495 pic16_emitcode ("push","b");
11496 pic16_emitcode ("push","acc");
11497 pic16_emitcode ("lcall","__gptrget");
11498 pic16_emitcode ("pop","b");
11504 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11505 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11506 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11507 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11508 // pic16_emitcode ("orl","a,b");
11511 // if (p_type == GPOINTER)
11512 // pic16_emitcode("pop","b");
11517 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11518 // pic16_emitcode("mov","@%s,a",rname);
11522 pic16_emitcode("movx","@dptr,a");
11526 DEBUGpic16_emitcode(";lcall","__gptrput");
11533 // pic16_freeAsmop(right, NULL, ic, TRUE);
11536 /*-----------------------------------------------------------------*/
11537 /* genDataPointerSet - remat pointer to data space */
11538 /*-----------------------------------------------------------------*/
11539 static void genDataPointerSet(operand *right,
11543 int size, offset = 0, resoffset=0 ;
11545 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11546 pic16_aopOp(right,ic,FALSE);
11548 size = AOP_SIZE(right);
11550 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11553 if ( AOP_TYPE(result) == AOP_PCODE) {
11554 fprintf(stderr,"genDataPointerSet %s, %d\n",
11555 AOP(result)->aopu.pcop->name,
11556 (AOP(result)->aopu.pcop->type == PO_DIR)?
11557 PCOR(AOP(result)->aopu.pcop)->instance:
11558 PCOI(AOP(result)->aopu.pcop)->offset);
11562 if(AOP(result)->aopu.pcop->type == PO_DIR)
11563 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11566 if (AOP_TYPE(right) == AOP_LIT) {
11569 if(!IS_FLOAT(operandType( right )))
11570 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11573 unsigned long lit_int;
11577 /* take care if literal is a float */
11578 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11579 lit = info.lit_int;
11582 lit = lit >> (8*offset);
11584 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11585 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11587 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11590 pic16_mov2w(AOP(right), offset);
11591 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11597 pic16_freeAsmop(right,NULL,ic,TRUE);
11602 /*-----------------------------------------------------------------*/
11603 /* genNearPointerSet - pic16_emitcode for near pointer put */
11604 /*-----------------------------------------------------------------*/
11605 static void genNearPointerSet (operand *right,
11611 sym_link *ptype = operandType(result);
11612 sym_link *resetype;
11614 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11615 retype= getSpec(operandType(right));
11616 resetype = getSpec(operandType(result));
11618 pic16_aopOp(result,ic,FALSE);
11620 /* if the result is rematerializable &
11621 * in data space & not a bit variable */
11623 /* and result is not a bit variable */
11624 if (AOP_TYPE(result) == AOP_PCODE
11625 // && AOP_TYPE(result) == AOP_IMMD
11626 && DCL_TYPE(ptype) == POINTER
11627 && !IS_BITFIELD(retype)
11628 && !IS_BITFIELD(resetype)) {
11630 genDataPointerSet (right,result,ic);
11631 pic16_freeAsmop(result,NULL,ic,TRUE);
11635 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11636 pic16_aopOp(right,ic,FALSE);
11637 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11639 /* if bitfield then unpack the bits */
11640 if (IS_BITFIELD(resetype)) {
11641 genPackBits (resetype, result, right, NULL, POINTER);
11643 /* we have can just get the values */
11644 int size = AOP_SIZE(right);
11647 pic16_loadFSR0(result, 0);
11649 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11651 if (AOP_TYPE(right) == AOP_LIT) {
11652 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11654 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11656 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11658 } else { // no literal
11660 pic16_emitpcode(POC_MOVFF,
11661 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11662 pic16_popCopyReg(&pic16_pc_postinc0)));
11664 pic16_emitpcode(POC_MOVFF,
11665 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11666 pic16_popCopyReg(&pic16_pc_indf0)));
11673 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11674 /* now some housekeeping stuff */
11676 /* we had to allocate for this iCode */
11677 pic16_freeAsmop(NULL,aop,ic,TRUE);
11679 /* we did not allocate which means left
11680 * already in a pointer register, then
11681 * if size > 0 && this could be used again
11682 * we have to point it back to where it
11684 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11685 if (AOP_SIZE(right) > 1
11686 && !OP_SYMBOL(result)->remat
11687 && ( OP_SYMBOL(result)->liveTo > ic->seq
11690 int size = AOP_SIZE(right) - 1;
11693 pic16_emitcode("decf","fsr0,f");
11694 //pic16_emitcode("dec","%s",rname);
11698 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11701 pic16_freeAsmop(right,NULL,ic,TRUE);
11702 pic16_freeAsmop(result,NULL,ic,TRUE);
11705 /*-----------------------------------------------------------------*/
11706 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11707 /*-----------------------------------------------------------------*/
11708 static void genPagedPointerSet (operand *right,
11713 regs *preg = NULL ;
11717 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11719 retype= getSpec(operandType(right));
11721 pic16_aopOp(result,ic,FALSE);
11723 /* if the value is already in a pointer register
11724 then don't need anything more */
11725 if (!AOP_INPREG(AOP(result))) {
11726 /* otherwise get a free pointer register */
11728 preg = getFreePtr(ic,&aop,FALSE);
11729 pic16_emitcode("mov","%s,%s",
11731 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11732 rname = preg->name ;
11734 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11736 pic16_freeAsmop(result,NULL,ic,TRUE);
11737 pic16_aopOp (right,ic,FALSE);
11739 /* if bitfield then unpack the bits */
11740 if (IS_BITFIELD(retype))
11741 genPackBits (retype,result,right,rname,PPOINTER);
11743 /* we have can just get the values */
11744 int size = AOP_SIZE(right);
11748 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11751 pic16_emitcode("movx","@%s,a",rname);
11754 pic16_emitcode("inc","%s",rname);
11760 /* now some housekeeping stuff */
11762 /* we had to allocate for this iCode */
11763 pic16_freeAsmop(NULL,aop,ic,TRUE);
11765 /* we did not allocate which means left
11766 already in a pointer register, then
11767 if size > 0 && this could be used again
11768 we have to point it back to where it
11770 if (AOP_SIZE(right) > 1 &&
11771 !OP_SYMBOL(result)->remat &&
11772 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11774 int size = AOP_SIZE(right) - 1;
11776 pic16_emitcode("dec","%s",rname);
11781 pic16_freeAsmop(right,NULL,ic,TRUE);
11787 /* This code is not adjusted to PIC16 and fails utterly...
11788 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11790 /*-----------------------------------------------------------------*/
11791 /* genFarPointerSet - set value from far space */
11792 /*-----------------------------------------------------------------*/
11793 static void genFarPointerSet (operand *right,
11794 operand *result, iCode *ic)
11797 sym_link *retype = getSpec(operandType(right));
11799 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11800 pic16_aopOp(result,ic,FALSE);
11802 /* if the operand is already in dptr
11803 then we do nothing else we move the value to dptr */
11804 if (AOP_TYPE(result) != AOP_STR) {
11805 /* if this is remateriazable */
11806 if (AOP_TYPE(result) == AOP_IMMD)
11807 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11808 else { /* we need to get it byte by byte */
11809 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11810 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11811 if (options.model == MODEL_FLAT24)
11813 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11817 /* so dptr know contains the address */
11818 pic16_freeAsmop(result,NULL,ic,TRUE);
11819 pic16_aopOp(right,ic,FALSE);
11821 /* if bit then unpack */
11822 if (IS_BITFIELD(retype))
11823 genPackBits(retype,result,right,"dptr",FPOINTER);
11825 size = AOP_SIZE(right);
11829 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11831 pic16_emitcode("movx","@dptr,a");
11833 pic16_emitcode("inc","dptr");
11837 pic16_freeAsmop(right,NULL,ic,TRUE);
11841 /*-----------------------------------------------------------------*/
11842 /* genGenPointerSet - set value from generic pointer space */
11843 /*-----------------------------------------------------------------*/
11845 static void genGenPointerSet (operand *right,
11846 operand *result, iCode *ic)
11848 int i, size, offset, lit;
11849 sym_link *retype = getSpec(operandType(right));
11851 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11853 pic16_aopOp(result,ic,FALSE);
11854 pic16_aopOp(right,ic,FALSE);
11855 size = AOP_SIZE(right);
11858 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11860 /* if the operand is already in dptr
11861 then we do nothing else we move the value to dptr */
11862 if (AOP_TYPE(result) != AOP_STR) {
11863 /* if this is remateriazable */
11864 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11865 // WARNING: anythig until "else" is untested!
11866 if (AOP_TYPE(result) == AOP_IMMD) {
11867 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11868 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11869 // load FSR0 from immediate
11870 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11874 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11876 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11882 else { /* we need to get it byte by byte */
11883 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11884 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11886 // set up FSR0 with address of result
11887 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11888 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11890 /* hack hack! see if this the FSR. If so don't load W */
11891 if(AOP_TYPE(right) != AOP_ACC) {
11893 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11895 if(AOP_TYPE(right) == AOP_LIT)
11898 // note: pic16_popGet handles sign extension
11899 for(i=0;i<size;i++) {
11900 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11902 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11904 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11909 for(i=0;i<size;i++) {
11911 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11912 pic16_popCopyReg(&pic16_pc_postinc0)));
11914 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11915 pic16_popCopyReg(&pic16_pc_indf0)));
11921 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11922 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11924 } // if (AOP_TYPE(result) != AOP_IMMD)
11926 } // if (AOP_TYPE(result) != AOP_STR)
11927 /* so dptr know contains the address */
11930 /* if bit then unpack */
11931 if (IS_BITFIELD(retype))
11932 genPackBits(retype,result,right,"dptr",GPOINTER);
11934 size = AOP_SIZE(right);
11937 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11939 // set up FSR0 with address of result
11940 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11941 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11944 if (AOP_TYPE(right) == AOP_LIT) {
11945 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11947 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11949 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11951 } else { // no literal
11953 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11955 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11963 pic16_freeAsmop(right,NULL,ic,TRUE);
11964 pic16_freeAsmop(result,NULL,ic,TRUE);
11968 static void genGenPointerSet (operand *right,
11969 operand *result, iCode *ic)
11972 sym_link *retype = getSpec(operandType(result));
11974 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11976 pic16_aopOp(result,ic,FALSE);
11977 pic16_aopOp(right,ic,FALSE);
11978 size = AOP_SIZE(right);
11980 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11983 /* if bit then unpack */
11984 if (IS_BITFIELD(retype)) {
11985 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11986 genPackBits(retype,result,right,"dptr",GPOINTER);
11990 size = AOP_SIZE(right);
11992 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11995 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11997 /* value of right+0 is placed on stack, which will be retrieved
11998 * by the support function this restoring the stack. The important
11999 * thing is that there is no need to manually restore stack pointer
12001 pushaop(AOP(right), 0);
12002 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12003 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12004 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12005 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12007 /* load address to write to in WREG:FSR0H:FSR0L */
12008 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12009 pic16_popCopyReg(&pic16_pc_fsr0l)));
12010 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12011 pic16_popCopyReg(&pic16_pc_prodl)));
12012 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12014 pic16_callGenericPointerRW(1, size);
12017 pic16_freeAsmop(right,NULL,ic,TRUE);
12018 pic16_freeAsmop(result,NULL,ic,TRUE);
12021 /*-----------------------------------------------------------------*/
12022 /* genPointerSet - stores the value into a pointer location */
12023 /*-----------------------------------------------------------------*/
12024 static void genPointerSet (iCode *ic)
12026 operand *right, *result ;
12027 sym_link *type, *etype;
12032 right = IC_RIGHT(ic);
12033 result = IC_RESULT(ic) ;
12035 /* depending on the type of pointer we need to
12036 move it to the correct pointer register */
12037 type = operandType(result);
12038 etype = getSpec(type);
12040 /* if left is of type of pointer then it is simple */
12041 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12042 p_type = DCL_TYPE(type);
12045 /* we have to go by the storage class */
12046 p_type = PTR_TYPE(SPEC_OCLS(etype));
12048 /* if (SPEC_OCLS(etype)->codesp ) { */
12049 /* p_type = CPOINTER ; */
12052 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12053 /* p_type = FPOINTER ; */
12055 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12056 /* p_type = PPOINTER ; */
12058 /* if (SPEC_OCLS(etype) == idata ) */
12059 /* p_type = IPOINTER ; */
12061 /* p_type = POINTER ; */
12064 /* now that we have the pointer type we assign
12065 the pointer values */
12070 genNearPointerSet (right,result,ic);
12074 genPagedPointerSet (right,result,ic);
12078 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12080 genFarPointerSet (right,result,ic);
12085 genGenPointerSet (right,result,ic);
12089 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12090 "genPointerSet: illegal pointer type");
12094 /*-----------------------------------------------------------------*/
12095 /* genIfx - generate code for Ifx statement */
12096 /*-----------------------------------------------------------------*/
12097 static void genIfx (iCode *ic, iCode *popIc)
12099 operand *cond = IC_COND(ic);
12104 pic16_aopOp(cond,ic,FALSE);
12106 /* get the value into acc */
12107 if (AOP_TYPE(cond) != AOP_CRY)
12108 pic16_toBoolean(cond);
12111 /* the result is now in the accumulator */
12112 pic16_freeAsmop(cond,NULL,ic,TRUE);
12114 /* if there was something to be popped then do it */
12118 /* if the condition is a bit variable */
12119 if (isbit && IS_ITEMP(cond) &&
12121 genIfxJump(ic,"c");
12122 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12124 if (isbit && !IS_ITEMP(cond))
12125 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12127 genIfxJump(ic,"a");
12132 /*-----------------------------------------------------------------*/
12133 /* genAddrOf - generates code for address of */
12134 /*-----------------------------------------------------------------*/
12135 static void genAddrOf (iCode *ic)
12137 operand *result, *left;
12139 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12140 pCodeOp *pcop0, *pcop1, *pcop2;
12144 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12146 sym = OP_SYMBOL( IC_LEFT(ic) );
12149 /* get address of symbol on stack */
12150 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12152 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12153 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12156 // operands on stack are accessible via "FSR2 + index" with index
12157 // starting at 2 for arguments and growing from 0 downwards for
12158 // local variables (index == 0 is not assigned so we add one here)
12160 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12162 assert (soffs < 0);
12165 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12166 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12167 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12168 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12169 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12170 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12171 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12177 // if(pic16_debug_verbose) {
12178 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12179 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12182 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12183 size = AOP_SIZE(IC_RESULT(ic));
12185 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12186 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12187 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12190 pic16_emitpcode(POC_MOVLW, pcop0);
12191 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12192 pic16_emitpcode(POC_MOVLW, pcop1);
12193 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12194 pic16_emitpcode(POC_MOVLW, pcop2);
12195 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12198 pic16_emitpcode(POC_MOVLW, pcop0);
12199 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12200 pic16_emitpcode(POC_MOVLW, pcop1);
12201 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12203 pic16_emitpcode(POC_MOVLW, pcop0);
12204 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12207 pic16_freeAsmop(left, NULL, ic, FALSE);
12209 pic16_freeAsmop(result,NULL,ic,TRUE);
12214 /*-----------------------------------------------------------------*/
12215 /* genFarFarAssign - assignment when both are in far space */
12216 /*-----------------------------------------------------------------*/
12217 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12219 int size = AOP_SIZE(right);
12222 /* first push the right side on to the stack */
12224 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12226 pic16_emitcode ("push","acc");
12229 pic16_freeAsmop(right,NULL,ic,FALSE);
12230 /* now assign DPTR to result */
12231 pic16_aopOp(result,ic,FALSE);
12232 size = AOP_SIZE(result);
12234 pic16_emitcode ("pop","acc");
12235 pic16_aopPut(AOP(result),"a",--offset);
12237 pic16_freeAsmop(result,NULL,ic,FALSE);
12242 /*-----------------------------------------------------------------*/
12243 /* genAssign - generate code for assignment */
12244 /*-----------------------------------------------------------------*/
12245 static void genAssign (iCode *ic)
12247 operand *result, *right;
12248 int size, offset,know_W;
12249 unsigned long lit = 0L;
12251 result = IC_RESULT(ic);
12252 right = IC_RIGHT(ic) ;
12256 /* if they are the same */
12257 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12260 /* reversed order operands are aopOp'ed so that result operand
12261 * is effective in case right is a stack symbol. This maneauver
12262 * allows to use the _G.resDirect flag later */
12263 pic16_aopOp(result,ic,TRUE);
12264 pic16_aopOp(right,ic,FALSE);
12266 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12268 /* if they are the same registers */
12269 if (pic16_sameRegs(AOP(right),AOP(result)))
12272 /* if the result is a bit */
12273 if (AOP_TYPE(result) == AOP_CRY) {
12274 /* if the right size is a literal then
12275 we know what the value is */
12276 if (AOP_TYPE(right) == AOP_LIT) {
12278 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12279 pic16_popGet(AOP(result),0));
12281 if (((int) operandLitValue(right)))
12282 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12283 AOP(result)->aopu.aop_dir,
12284 AOP(result)->aopu.aop_dir);
12286 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12287 AOP(result)->aopu.aop_dir,
12288 AOP(result)->aopu.aop_dir);
12292 /* the right is also a bit variable */
12293 if (AOP_TYPE(right) == AOP_CRY) {
12294 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12295 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12296 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12298 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12299 AOP(result)->aopu.aop_dir,
12300 AOP(result)->aopu.aop_dir);
12301 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12302 AOP(right)->aopu.aop_dir,
12303 AOP(right)->aopu.aop_dir);
12304 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12305 AOP(result)->aopu.aop_dir,
12306 AOP(result)->aopu.aop_dir);
12310 /* we need to or */
12311 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12312 pic16_toBoolean(right);
12314 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12315 //pic16_aopPut(AOP(result),"a",0);
12319 /* bit variables done */
12321 size = AOP_SIZE(result);
12324 if(AOP_TYPE(right) == AOP_LIT) {
12325 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12326 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12329 unsigned long lit_int;
12334 if(IS_FIXED16X16(operandType(right))) {
12335 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12337 /* take care if literal is a float */
12338 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12339 lit = info.lit_int;
12344 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12345 // sizeof(unsigned long int), sizeof(float));
12348 if (AOP_TYPE(right) == AOP_REG) {
12349 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12351 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12356 /* when do we have to read the program memory?
12357 * - if right itself is a symbol in code space
12358 * (we don't care what it points to if it's a pointer)
12359 * - AND right is not a function (we would want its address)
12361 if(AOP_TYPE(right) != AOP_LIT
12362 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12363 && !IS_FUNC(OP_SYM_TYPE(right))
12364 && !IS_ITEMP(right))
12366 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12367 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12369 // set up table pointer
12370 if(is_LitOp(right)) {
12371 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12372 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12373 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12374 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12375 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12376 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12377 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12379 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12380 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12381 pic16_popCopyReg(&pic16_pc_tblptrl)));
12382 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12383 pic16_popCopyReg(&pic16_pc_tblptrh)));
12384 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12385 pic16_popCopyReg(&pic16_pc_tblptru)));
12388 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12389 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12391 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12392 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12393 pic16_popGet(AOP(result),offset)));
12397 /* FIXME: for pointers we need to extend differently (according
12398 * to pointer type DATA/CODE/EEPROM/... :*/
12399 size = getSize(OP_SYM_TYPE(right));
12400 if(AOP_SIZE(result) > size) {
12401 size = AOP_SIZE(result) - size;
12403 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12410 if (AOP_TYPE(right) == AOP_LIT && IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result)))
12412 /* Arrg -- a literal is cast into a generic pointer: how shall we decide which TAG
12413 * to assign (__data, __code, __eeprom, ???)??? */
12414 fprintf (stderr, "%s:%u(%s): creating generic pointer from literal defaults to __data TYPE*.\n\tPlease explicitly cast to (__data|__code) TYPE* in line %u if neccessary!\n",
12415 __FILE__, __LINE__, __FUNCTION__, ic->lineno);
12416 /* assume __data space */
12417 lit = (lit & 0x00ffff) | 0x800000;
12423 /* VR - What is this?! */
12424 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12425 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12426 if(aopIdx(AOP(result),0) == 4) {
12428 /* this is a workaround to save value of right into wreg too,
12429 * value of wreg is going to be used later */
12430 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12431 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12432 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12436 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12442 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12443 if(AOP_TYPE(right) == AOP_LIT) {
12445 if(know_W != (lit&0xff))
12446 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12448 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12450 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12454 } else if (AOP_TYPE(right) == AOP_CRY) {
12455 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12457 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12458 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12459 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12461 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12462 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12463 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12465 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12467 if(!_G.resDirect) /* use this aopForSym feature */
12468 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12475 pic16_freeAsmop (right,NULL,ic,FALSE);
12476 pic16_freeAsmop (result,NULL,ic,TRUE);
12479 /*-----------------------------------------------------------------*/
12480 /* genJumpTab - generates code for jump table */
12481 /*-----------------------------------------------------------------*/
12482 static void genJumpTab (iCode *ic)
12487 pCodeOp *jt_offs_hi;
12492 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12493 /* get the condition into accumulator */
12494 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12496 /* multiply by three */
12497 pic16_emitcode("add","a,acc");
12498 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12500 jtab = newiTempLabel(NULL);
12501 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12502 pic16_emitcode("jmp","@a+dptr");
12503 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12506 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12507 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12509 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12510 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12511 pic16_emitpLabel(jtab->key);
12515 jt_offs = pic16_popGetTempReg(0);
12516 jt_offs_hi = pic16_popGetTempReg(1);
12517 jt_label = pic16_popGetLabel (jtab->key);
12518 //fprintf (stderr, "Creating jump table...\n");
12520 // calculate offset into jump table (idx * sizeof (GOTO))
12521 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12522 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12523 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12524 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12525 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12526 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12527 pic16_emitpcode(POC_MOVWF , jt_offs);
12529 // prepare PCLATx (set to first entry in jump table)
12530 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12531 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12532 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12533 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12534 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12536 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12537 pic16_emitpcode(POC_ADDWF , jt_offs);
12538 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12539 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12541 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12543 // release temporaries and prepare jump into table (new PCL --> WREG)
12544 pic16_emitpcode(POC_MOVFW , jt_offs);
12545 pic16_popReleaseTempReg (jt_offs_hi, 1);
12546 pic16_popReleaseTempReg (jt_offs, 0);
12548 // jump into the table
12549 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12551 pic16_emitpLabelFORCE(jtab->key);
12554 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12555 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12557 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12558 /* now generate the jump labels */
12559 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12560 jtab = setNextItem(IC_JTLABELS(ic))) {
12561 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12562 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12565 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12569 /*-----------------------------------------------------------------*/
12570 /* genMixedOperation - gen code for operators between mixed types */
12571 /*-----------------------------------------------------------------*/
12573 TSD - Written for the PIC port - but this unfortunately is buggy.
12574 This routine is good in that it is able to efficiently promote
12575 types to different (larger) sizes. Unfortunately, the temporary
12576 variables that are optimized out by this routine are sometimes
12577 used in other places. So until I know how to really parse the
12578 iCode tree, I'm going to not be using this routine :(.
12580 static int genMixedOperation (iCode *ic)
12583 operand *result = IC_RESULT(ic);
12584 sym_link *ctype = operandType(IC_LEFT(ic));
12585 operand *right = IC_RIGHT(ic);
12591 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12593 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12599 nextright = IC_RIGHT(nextic);
12600 nextleft = IC_LEFT(nextic);
12601 nextresult = IC_RESULT(nextic);
12603 pic16_aopOp(right,ic,FALSE);
12604 pic16_aopOp(result,ic,FALSE);
12605 pic16_aopOp(nextright, nextic, FALSE);
12606 pic16_aopOp(nextleft, nextic, FALSE);
12607 pic16_aopOp(nextresult, nextic, FALSE);
12609 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12611 operand *t = right;
12615 pic16_emitcode(";remove right +","");
12617 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12619 operand *t = right;
12623 pic16_emitcode(";remove left +","");
12627 big = AOP_SIZE(nextleft);
12628 small = AOP_SIZE(nextright);
12630 switch(nextic->op) {
12633 pic16_emitcode(";optimize a +","");
12634 /* if unsigned or not an integral type */
12635 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12636 pic16_emitcode(";add a bit to something","");
12639 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12641 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12642 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12643 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12645 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12653 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12654 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12655 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12658 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12660 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12661 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12662 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12663 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12664 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12667 pic16_emitcode("rlf","known_zero,w");
12674 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12675 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12676 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12678 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12688 pic16_freeAsmop(right,NULL,ic,TRUE);
12689 pic16_freeAsmop(result,NULL,ic,TRUE);
12690 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12691 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12693 nextic->generated = 1;
12700 /*-----------------------------------------------------------------*/
12701 /* genCast - gen code for casting */
12702 /*-----------------------------------------------------------------*/
12703 static void genCast (iCode *ic)
12705 operand *result = IC_RESULT(ic);
12706 sym_link *ctype = operandType(IC_LEFT(ic));
12707 sym_link *rtype = operandType(IC_RIGHT(ic));
12708 sym_link *restype = operandType(IC_RESULT(ic));
12709 operand *right = IC_RIGHT(ic);
12715 /* if they are equivalent then do nothing */
12716 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12719 pic16_aopOp(result,ic,FALSE);
12720 pic16_aopOp(right,ic,FALSE) ;
12722 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12725 /* if the result is a bit */
12726 if (AOP_TYPE(result) == AOP_CRY) {
12728 /* if the right size is a literal then
12729 * we know what the value is */
12730 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12732 if (AOP_TYPE(right) == AOP_LIT) {
12733 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12734 pic16_popGet(AOP(result),0));
12736 if (((int) operandLitValue(right)))
12737 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12738 AOP(result)->aopu.aop_dir,
12739 AOP(result)->aopu.aop_dir);
12741 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12742 AOP(result)->aopu.aop_dir,
12743 AOP(result)->aopu.aop_dir);
12747 /* the right is also a bit variable */
12748 if (AOP_TYPE(right) == AOP_CRY) {
12750 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12752 pic16_emitcode("clrc","");
12753 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12754 AOP(right)->aopu.aop_dir,
12755 AOP(right)->aopu.aop_dir);
12756 pic16_aopPut(AOP(result),"c",0);
12760 /* we need to or */
12761 if (AOP_TYPE(right) == AOP_REG) {
12762 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12763 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12764 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12766 pic16_toBoolean(right);
12767 pic16_aopPut(AOP(result),"a",0);
12771 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12774 size = AOP_SIZE(result);
12776 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12778 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12779 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12780 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12783 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12788 if(IS_BITFIELD(getSpec(restype))
12789 && IS_BITFIELD(getSpec(rtype))) {
12790 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12793 /* port from pic14 to cope with generic pointers */
12794 if (IS_PTR(restype))
12796 operand *result = IC_RESULT(ic);
12797 //operand *left = IC_LEFT(ic);
12798 operand *right = IC_RIGHT(ic);
12801 /* copy common part */
12802 int max, size = AOP_SIZE(result);
12803 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12804 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12806 /* warn if we discard generic opinter tag */
12807 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
12809 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
12815 pic16_mov2w (AOP(right), size);
12816 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12818 pic16_addSign(result, max, 0);
12820 /* upcast into generic pointer type? */
12821 if (IS_GENPTR(restype) && !IS_GENPTR(rtype))
12823 //fprintf (stderr, "%s:%u: must determine pointer type (IS_PTR: %d, DCL_TYPE: %d)\n", __FUNCTION__, __LINE__, IS_PTR(rtype), IS_PTR(rtype) ? DCL_TYPE(rtype) : 0);
12826 switch (DCL_TYPE(rtype))
12828 case POINTER: /* __data */
12829 case FPOINTER: /* __data */
12830 assert (AOP_SIZE(right) == 2);
12834 case CPOINTER: /* __code */
12835 assert (AOP_SIZE(right) == 2);
12839 case GPOINTER: /* unknown destination, __data or __code */
12840 assert (AOP_SIZE(right) == 3);
12841 /* tag taken from right operand */
12845 assert (!"unhandled pointer type");
12848 /* convert other values into pointers to __data space */
12849 fprintf (stderr, "%s:%u(%s): creating generic pointer from non-pointer type -- assuming __data space\n", __FILE__, __LINE__, __FUNCTION__);
12853 assert (AOP_SIZE(result) == 3);
12855 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 2));
12857 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(tag));
12858 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), 2));
12864 /* if they are the same size : or less */
12865 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12867 /* if they are in the same place */
12868 if (pic16_sameRegs(AOP(right),AOP(result)))
12871 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12873 if (IS_PTR_CONST(rtype))
12875 if (IS_CODEPTR(rtype))
12877 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12880 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12882 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12884 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12887 if(AOP_TYPE(right) == AOP_IMMD) {
12888 pCodeOp *pcop0, *pcop1, *pcop2;
12889 symbol *sym = OP_SYMBOL( right );
12891 size = AOP_SIZE(result);
12893 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12895 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12897 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12900 pic16_emitpcode(POC_MOVLW, pcop0);
12901 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12902 pic16_emitpcode(POC_MOVLW, pcop1);
12903 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12904 pic16_emitpcode(POC_MOVLW, pcop2);
12905 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12908 pic16_emitpcode(POC_MOVLW, pcop0);
12909 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12910 pic16_emitpcode(POC_MOVLW, pcop1);
12911 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12913 pic16_emitpcode(POC_MOVLW, pcop0);
12914 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12918 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12919 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12920 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12921 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12922 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12923 if(AOP_SIZE(result) <2)
12924 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12926 /* if they in different places then copy */
12927 size = AOP_SIZE(result);
12930 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12931 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12938 /* if the result is of type pointer */
12939 if (IS_PTR(ctype)) {
12941 sym_link *type = operandType(right);
12942 sym_link *etype = getSpec(type);
12944 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12946 /* pointer to generic pointer */
12947 if (IS_GENPTR(ctype)) {
12951 p_type = DCL_TYPE(type);
12953 /* we have to go by the storage class */
12954 p_type = PTR_TYPE(SPEC_OCLS(etype));
12956 /* if (SPEC_OCLS(etype)->codesp ) */
12957 /* p_type = CPOINTER ; */
12959 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12960 /* p_type = FPOINTER ; */
12962 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12963 /* p_type = PPOINTER; */
12965 /* if (SPEC_OCLS(etype) == idata ) */
12966 /* p_type = IPOINTER ; */
12968 /* p_type = POINTER ; */
12971 /* the first two bytes are known */
12972 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
12973 size = GPTRSIZE - 1;
12976 if(offset < AOP_SIZE(right)) {
12977 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12978 pic16_mov2f(AOP(result), AOP(right), offset);
12980 if ((AOP_TYPE(right) == AOP_PCODE) &&
12981 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12982 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12983 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12986 pic16_aopPut(AOP(result),
12987 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12992 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12995 /* the last byte depending on type */
12999 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13000 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13001 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13005 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13009 pic16_emitcode(";BUG!? ","%d",__LINE__);
13013 pic16_emitcode(";BUG!? ","%d",__LINE__);
13018 if (GPTRSIZE > AOP_SIZE(right)) {
13019 // assume data pointer... THIS MIGHT BE WRONG!
13020 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13021 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13023 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13028 /* this should never happen */
13029 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13030 "got unknown pointer type");
13033 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13039 /* just copy the pointers */
13040 size = AOP_SIZE(result);
13043 pic16_aopPut(AOP(result),
13044 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13053 /* so we now know that the size of destination is greater
13054 than the size of the source.
13055 Now, if the next iCode is an operator then we might be
13056 able to optimize the operation without performing a cast.
13058 if(genMixedOperation(ic))
13061 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13063 /* we move to result for the size of source */
13064 size = AOP_SIZE(right);
13069 pic16_mov2f(AOP(result), AOP(right), offset);
13073 /* now depending on the sign of the destination */
13074 size = AOP_SIZE(result) - AOP_SIZE(right);
13075 /* if unsigned or not an integral type */
13076 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13078 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13080 /* we need to extend the sign :( */
13083 /* Save one instruction of casting char to int */
13084 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13085 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13086 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13088 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13091 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13093 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13095 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13098 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13103 pic16_freeAsmop(right,NULL,ic,TRUE);
13104 pic16_freeAsmop(result,NULL,ic,TRUE);
13108 /*-----------------------------------------------------------------*/
13109 /* genDjnz - generate decrement & jump if not zero instrucion */
13110 /*-----------------------------------------------------------------*/
13111 static int genDjnz (iCode *ic, iCode *ifx)
13113 symbol *lbl, *lbl1;
13114 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13119 /* if the if condition has a false label
13120 then we cannot save */
13124 /* if the minus is not of the form
13126 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13127 !IS_OP_LITERAL(IC_RIGHT(ic)))
13130 if (operandLitValue(IC_RIGHT(ic)) != 1)
13133 /* if the size of this greater than one then no
13135 if (getSize(operandType(IC_RESULT(ic))) > 1)
13138 /* otherwise we can save BIG */
13139 lbl = newiTempLabel(NULL);
13140 lbl1= newiTempLabel(NULL);
13142 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13144 if (IS_AOP_PREG(IC_RESULT(ic))) {
13145 pic16_emitcode("dec","%s",
13146 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13147 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13148 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13152 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13153 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13155 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13156 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13160 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13161 ifx->generated = 1;
13165 /*-----------------------------------------------------------------*/
13166 /* genReceive - generate code for a receive iCode */
13167 /*-----------------------------------------------------------------*/
13168 static void genReceive (iCode *ic)
13174 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13175 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13177 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13179 if (isOperandInFarSpace(IC_RESULT(ic))
13180 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13181 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13183 int size = getSize(operandType(IC_RESULT(ic)));
13184 int offset = pic16_fReturnSizePic - size;
13188 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13189 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13193 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13195 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13196 size = AOP_SIZE(IC_RESULT(ic));
13199 pic16_emitcode ("pop","acc");
13200 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13203 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13205 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13208 /* set pseudo stack pointer to where it should be - dw*/
13209 GpsuedoStkPtr = ic->parmBytes;
13211 /* setting GpsuedoStkPtr has side effects here: */
13212 assignResultValue(IC_RESULT(ic), 0);
13215 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13218 /*-----------------------------------------------------------------*/
13219 /* genDummyRead - generate code for dummy read of volatiles */
13220 /*-----------------------------------------------------------------*/
13222 genDummyRead (iCode * ic)
13228 if (op && IS_SYMOP(op)) {
13229 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13230 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13233 pic16_aopOp (op, ic, FALSE);
13234 for (i=0; i < AOP_SIZE(op); i++) {
13235 // may need to protect this from the peepholer -- this is not nice but works...
13236 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13237 pic16_mov2w (AOP(op),i);
13238 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13240 pic16_freeAsmop (op, NULL, ic, TRUE);
13242 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13246 /*-----------------------------------------------------------------*/
13247 /* genpic16Code - generate code for pic16 based controllers */
13248 /*-----------------------------------------------------------------*/
13250 * At this point, ralloc.c has gone through the iCode and attempted
13251 * to optimize in a way suitable for a PIC. Now we've got to generate
13252 * PIC instructions that correspond to the iCode.
13254 * Once the instructions are generated, we'll pass through both the
13255 * peep hole optimizer and the pCode optimizer.
13256 *-----------------------------------------------------------------*/
13258 void genpic16Code (iCode *lic)
13263 lineHead = lineCurr = NULL;
13265 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13266 pic16_addpBlock(pb);
13269 /* if debug information required */
13270 if (options.debug && currFunc) {
13272 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13277 for (ic = lic ; ic ; ic = ic->next ) {
13279 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13280 if ( cln != ic->lineno ) {
13281 if ( options.debug ) {
13282 debugFile->writeCLine (ic);
13285 if(!options.noCcodeInAsm) {
13286 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13287 printCLine(ic->filename, ic->lineno)));
13293 if(options.iCodeInAsm) {
13296 /* insert here code to print iCode as comment */
13297 l = Safe_strdup(printILine(ic));
13298 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13301 /* if the result is marked as
13302 * spilt and rematerializable or code for
13303 * this has already been generated then
13305 if (resultRemat(ic) || ic->generated )
13308 /* depending on the operation */
13327 /* IPOP happens only when trying to restore a
13328 * spilt live range, if there is an ifx statement
13329 * following this pop then the if statement might
13330 * be using some of the registers being popped which
13331 * would destroy the contents of the register so
13332 * we need to check for this condition and handle it */
13334 && ic->next->op == IFX
13335 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13336 genIfx (ic->next,ic);
13354 genEndFunction (ic);
13370 pic16_genPlus (ic) ;
13374 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13375 pic16_genMinus (ic);
13391 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13395 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13401 /* note these two are xlated by algebraic equivalence
13402 * during parsing SDCC.y */
13403 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13404 "got '>=' or '<=' shouldn't have come here");
13408 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13420 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13424 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13428 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13452 genRightShift (ic);
13455 case GET_VALUE_AT_ADDRESS:
13460 if (POINTER_SET(ic))
13487 addSet(&_G.sendSet,ic);
13490 case DUMMY_READ_VOLATILE:
13500 /* now we are ready to call the
13501 peep hole optimizer */
13502 if (!options.nopeep)
13503 peepHole (&lineHead);
13505 /* now do the actual printing */
13506 printLine (lineHead, codeOutFile);
13509 DFPRINTF((stderr,"printing pBlock\n\n"));
13510 pic16_printpBlock(stdout,pb);