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)
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 In other words, you are welcome to use, share and improve this program.
26 You are forbidden to forbid anyone else to use, share and improve
27 what you give them. Help stamp out software-hoarding!
30 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
31 Made everything static
32 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
50 /* Set the following to 1 to enable the slower/bigger
51 * but more robust generic shifting routine (which also
52 * operates correctly with negative shift values). */
53 #define USE_GENERIC_SIGNED_SHIFT 1
55 /* Set the following to 1 to enable the new
56 * stripped down genCmp version.
57 * This version should be easier to understand,
58 * more reliable and (sigh) slighly slower. */
59 #define USE_SIMPLE_GENCMP 1
61 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
62 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 void pic16_genMult8X8_8 (operand *, operand *,operand *);
64 void pic16_genMult16X16_16(operand *, operand *, operand *);
65 void pic16_genMult32X32_32(operand *, operand *, operand *);
66 pCode *pic16_AssembleLine(char *line, int peeps);
67 extern void pic16_printpBlock(FILE *of, pBlock *pb);
68 static asmop *newAsmop (short type);
69 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
70 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
71 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
72 static pCodeOp *pic16_popRegFromIdx(int rIdx);
74 //static int aopIdx (asmop *aop, int offset);
76 int pic16_labelOffset=0;
77 extern int pic16_debug_verbose;
78 #if !(USE_GENERIC_SIGNED_SHIFT)
79 static int optimized_for_speed = 0;
88 /* max_key keeps track of the largest label number used in
89 a function. This is then used to adjust the label offset
90 for the next function.
93 static int GpsuedoStkPtr=0;
95 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
97 unsigned int pic16aopLiteral (value *val, int offset);
98 const char *pic16_AopType(short type);
99 static iCode *ifxForOp ( operand *op, iCode *ic );
101 void pic16_pushpCodeOp(pCodeOp *pcop);
102 void pic16_poppCodeOp(pCodeOp *pcop);
104 static bool is_LitOp(operand *op);
105 static bool is_LitAOp(asmop *aop);
108 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
110 /* set the following macro to 1 to enable passing the
111 * first byte of functions parameters via WREG */
112 #define USE_WREG_IN_FUNC_PARAMS 0
115 /* this is the down and dirty file with all kinds of
116 kludgy & hacky stuff. This is what it is all about
117 CODE GENERATION for a specific MCU . some of the
118 routines may be reusable, will have to see */
120 static char *zero = "#0x00";
121 static char *one = "#0x01";
122 //static char *spname = "sp";
126 * Function return value policy (MSB-->LSB):
128 * 16 bits -> PRODL:WREG
129 * 24 bits -> PRODH:PRODL:WREG
130 * 32 bits -> FSR0L:PRODH:PRODL:WREG
131 * >32 bits -> on stack, and FSR0 points to the beginning
136 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
137 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
138 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
139 static char **fReturn = fReturnpic16;
141 static char *accUse[] = {"WREG"};
143 //static short rbank = -1;
157 bitVect *fregsUsed; /* registers used in function */
159 set *sregsAllocSet; /* registers used to store stack variables */
160 int stack_lat; /* stack offset latency */
162 int useWreg; /* flag when WREG is used to pass function parameter */
165 extern int pic16_ptrRegReq ;
166 extern int pic16_nRegs;
167 extern FILE *codeOutFile;
168 //static void saverbank (int, iCode *,bool);
170 static lineNode *lineHead = NULL;
171 static lineNode *lineCurr = NULL;
173 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
174 0xE0, 0xC0, 0x80, 0x00};
175 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
176 0x07, 0x03, 0x01, 0x00};
180 /*-----------------------------------------------------------------*/
181 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
182 /* exponent of 2 is returned, otherwise -1 is */
184 /* note that this is similar to the function `powof2' in SDCCsymt */
188 /*-----------------------------------------------------------------*/
189 int pic16_my_powof2 (unsigned long num)
192 if( (num & (num-1)) == 0) {
205 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
207 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
209 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
210 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
211 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
212 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
213 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
214 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
215 ((result) ? AOP_SIZE(result) : 0));
218 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
221 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
223 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
224 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
225 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
226 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
227 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
228 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
232 void pic16_emitpcomment (char *fmt, ...)
235 char lb[INITIAL_INLINEASM];
241 vsprintf(lb+1,fmt,ap);
243 while (isspace(*lbp)) lbp++;
246 lineCurr = (lineCurr ?
247 connectLine(lineCurr,newLineNode(lb)) :
248 (lineHead = newLineNode(lb)));
249 lineCurr->isInline = _G.inLine;
250 lineCurr->isDebug = _G.debugLine;
252 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
255 // fprintf(stderr, "%s\n", lb);
258 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
261 char lb[INITIAL_INLINEASM];
264 if(!pic16_debug_verbose)
271 sprintf(lb,"%s\t",inst);
273 sprintf(lb,"%s",inst);
274 vsprintf(lb+(strlen(lb)),fmt,ap);
278 while (isspace(*lbp)) lbp++;
281 lineCurr = (lineCurr ?
282 connectLine(lineCurr,newLineNode(lb)) :
283 (lineHead = newLineNode(lb)));
284 lineCurr->isInline = _G.inLine;
285 lineCurr->isDebug = _G.debugLine;
287 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
290 // fprintf(stderr, "%s\n", lb);
295 void pic16_emitpLabel(int key)
297 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
300 void pic16_emitpLabelFORCE(int key)
302 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
305 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
309 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
311 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
314 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
317 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
319 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
322 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
325 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
331 #define pic16_emitcode DEBUGpic16_emitcode
333 /*-----------------------------------------------------------------*/
334 /* pic16_emitcode - writes the code into a file : for now it is simple */
335 /*-----------------------------------------------------------------*/
336 void pic16_emitcode (char *inst,char *fmt, ...)
339 char lb[INITIAL_INLINEASM];
346 sprintf(lb,"%s\t",inst);
348 sprintf(lb,"%s",inst);
349 vsprintf(lb+(strlen(lb)),fmt,ap);
353 while (isspace(*lbp)) lbp++;
356 lineCurr = (lineCurr ?
357 connectLine(lineCurr,newLineNode(lb)) :
358 (lineHead = newLineNode(lb)));
359 lineCurr->isInline = _G.inLine;
360 lineCurr->isDebug = _G.debugLine;
362 // VR fprintf(stderr, "lb = <%s>\n", lbp);
364 // if(pic16_debug_verbose)
365 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
372 /*-----------------------------------------------------------------*/
373 /* pic16_emitDebuggerSymbol - associate the current code location */
374 /* with a debugger symbol */
375 /*-----------------------------------------------------------------*/
377 pic16_emitDebuggerSymbol (char * debugSym)
380 pic16_emitcode (";", "%s ==.", debugSym);
385 /*-----------------------------------------------------------------*/
386 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
387 /*-----------------------------------------------------------------*/
388 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
390 // bool r0iu = FALSE , r1iu = FALSE;
391 // bool r0ou = FALSE , r1ou = FALSE;
392 bool fsr0iu = FALSE, fsr0ou;
393 bool fsr2iu = FALSE, fsr2ou;
395 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
398 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
399 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
401 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
402 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
404 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
405 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
406 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
409 if(!fsr0iu && !fsr0ou) {
410 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
411 (*aopp)->type = AOP_FSR0;
413 fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
415 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
419 /* no usage of FSR2 */
420 if(!fsr2iu && !fsr2ou) {
421 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
422 (*aopp)->type = AOP_FSR2;
424 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
428 /* now we know they both have usage */
429 /* if fsr0 not used in this instruction */
431 if (!_G.fsr0Pushed) {
432 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
433 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
437 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
438 (*aopp)->type = AOP_FSR0;
440 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
442 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
446 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
451 /* the logic: if r0 & r1 used in the instruction
452 then we are in trouble otherwise */
454 /* first check if r0 & r1 are used by this
455 instruction, in which case we are in trouble */
456 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
457 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
462 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
463 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
465 /* if no usage of r0 then return it */
466 if (!r0iu && !r0ou) {
467 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
468 (*aopp)->type = AOP_R0;
470 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
473 /* if no usage of r1 then return it */
474 if (!r1iu && !r1ou) {
475 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
476 (*aopp)->type = AOP_R1;
478 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
481 /* now we know they both have usage */
482 /* if r0 not used in this instruction */
484 /* push it if not already pushed */
486 //pic16_emitcode ("push","%s",
487 // pic16_regWithIdx(R0_IDX)->dname);
491 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
492 (*aopp)->type = AOP_R0;
494 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
497 /* if r1 not used then */
500 /* push it if not already pushed */
502 //pic16_emitcode ("push","%s",
503 // pic16_regWithIdx(R1_IDX)->dname);
507 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
508 (*aopp)->type = AOP_R1;
509 return pic16_regWithIdx(R1_IDX);
513 /* I said end of world but not quite end of world yet */
514 /* if this is a result then we can push it on the stack*/
516 (*aopp)->type = AOP_STK;
520 /* other wise this is true end of the world */
521 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
522 "getFreePtr should never reach here");
527 /*-----------------------------------------------------------------*/
528 /* newAsmop - creates a new asmOp */
529 /*-----------------------------------------------------------------*/
530 static asmop *newAsmop (short type)
534 aop = Safe_calloc(1,sizeof(asmop));
539 static void genSetDPTR(int n)
543 pic16_emitcode(";", "Select standard DPTR");
544 pic16_emitcode("mov", "dps, #0x00");
548 pic16_emitcode(";", "Select alternate DPTR");
549 pic16_emitcode("mov", "dps, #0x01");
553 /*-----------------------------------------------------------------*/
554 /* resolveIfx - converts an iCode ifx into a form more useful for */
555 /* generating code */
556 /*-----------------------------------------------------------------*/
557 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
561 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
567 resIfx->condition = 1; /* assume that the ifx is true */
568 resIfx->generated = 0; /* indicate that the ifx has not been used */
571 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
574 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
575 __FUNCTION__,__LINE__,resIfx->lbl->key);
580 resIfx->lbl = IC_TRUE(ifx);
582 resIfx->lbl = IC_FALSE(ifx);
583 resIfx->condition = 0;
588 DEBUGpic16_emitcode("; +++","ifx true is non-null");
590 DEBUGpic16_emitcode("; +++","ifx true is null");
592 DEBUGpic16_emitcode("; +++","ifx false is non-null");
594 DEBUGpic16_emitcode("; +++","ifx false is null");
598 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
602 /*-----------------------------------------------------------------*/
603 /* pointerCode - returns the code for a pointer type */
604 /*-----------------------------------------------------------------*/
605 static int pointerCode (sym_link *etype)
608 return PTR_TYPE(SPEC_OCLS(etype));
613 /*-----------------------------------------------------------------*/
614 /* aopForSym - for a true symbol */
615 /*-----------------------------------------------------------------*/
616 static asmop *aopForSym (iCode *ic, operand *op, bool result)
618 symbol *sym=OP_SYMBOL(op);
620 memmap *space= SPEC_OCLS(sym->etype);
624 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
626 // sym = OP_SYMBOL(op);
628 /* if already has one */
630 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
635 /* if symbol was initially placed onStack then we must re-place it
636 * to direct memory, since pic16 does not have a specific stack */
638 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
646 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
648 sym->aop = aop = newAsmop (AOP_PAGED);
649 aop->aopu.aop_dir = sym->rname ;
650 aop->size = getSize(sym->type);
651 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
652 pic16_allocDirReg( IC_LEFT(ic) );
660 /* assign depending on the storage class */
661 /* if it is on the stack or indirectly addressable */
662 /* space we need to assign either r0 or r1 to it */
663 if (sym->onStack) // || sym->iaccess)
668 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
669 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
671 /* acquire a temporary register -- it is saved in function */
673 sym->aop = aop = newAsmop(AOP_STA);
674 aop->aopu.stk.stk = sym->stack;
675 aop->size = getSize(sym->type);
678 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
679 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
680 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
681 // pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
683 for(i=0;i<aop->size;i++)
684 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
685 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
687 if(1 && ic->op == SEND) {
689 /* if SEND do the send here */
692 for(i=0;i<aop->size;i++) {
693 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
694 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
699 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
702 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
704 // we do not need to load the value if it is to be defined...
705 if (result) return aop;
708 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
711 for(i=0;i<aop->size;i++) {
713 /* initialise for stack access via frame pointer */
714 // operands on stack are accessible via "FSR2 + index" with index
715 // starting at 2 for arguments and growing from 0 downwards for
716 // local variables (index == 0 is not assigned so we add one here)
718 int soffs = sym->stack;
724 if(1 && ic->op == SEND) {
725 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
726 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
727 pic16_popCopyReg( pic16_frame_plusw ),
728 pic16_popCopyReg(pic16_stack_postdec )));
730 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
731 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
732 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
738 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
745 /* now assign the address of the variable to
746 the pointer register */
747 if (aop->type != AOP_STK) {
751 pic16_emitcode("push","acc");
753 pic16_emitcode("mov","a,_bp");
754 pic16_emitcode("add","a,#0x%02x",
756 ((char)(sym->stack - _G.nRegsSaved )) :
757 ((char)sym->stack)) & 0xff);
758 pic16_emitcode("mov","%s,a",
759 aop->aopu.aop_ptr->name);
762 pic16_emitcode("pop","acc");
764 pic16_emitcode("mov","%s,#%s",
765 aop->aopu.aop_ptr->name,
767 aop->paged = space->paged;
769 aop->aopu.aop_stk = sym->stack;
777 if (sym->onStack && options.stack10bit)
779 /* It's on the 10 bit stack, which is located in
783 //DEBUGpic16_emitcode(";","%d",__LINE__);
786 pic16_emitcode("push","acc");
788 pic16_emitcode("mov","a,_bp");
789 pic16_emitcode("add","a,#0x%02x",
791 ((char)(sym->stack - _G.nRegsSaved )) :
792 ((char)sym->stack)) & 0xff);
795 pic16_emitcode ("mov","dpx1,#0x40");
796 pic16_emitcode ("mov","dph1,#0x00");
797 pic16_emitcode ("mov","dpl1, a");
801 pic16_emitcode("pop","acc");
803 sym->aop = aop = newAsmop(AOP_DPTR2);
804 aop->size = getSize(sym->type);
810 /* special case for a function */
811 if (IS_FUNC(sym->type)) {
812 sym->aop = aop = newAsmop(AOP_PCODE);
813 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
814 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
815 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
816 PCOI(aop->aopu.pcop)->index = 0;
817 aop->size = FPTRSIZE;
818 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
825 //DEBUGpic16_emitcode(";","%d",__LINE__);
826 /* if in bit space */
827 if (IN_BITSPACE(space)) {
828 sym->aop = aop = newAsmop (AOP_CRY);
829 aop->aopu.aop_dir = sym->rname ;
830 aop->size = getSize(sym->type);
831 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
834 /* if it is in direct space */
835 if (IN_DIRSPACE(space)) {
836 sym->aop = aop = newAsmop (AOP_DIR);
837 aop->aopu.aop_dir = sym->rname ;
838 aop->size = getSize(sym->type);
839 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
840 pic16_allocDirReg( IC_LEFT(ic) );
845 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
846 sym->aop = aop = newAsmop (AOP_DIR);
847 aop->aopu.aop_dir = sym->rname ;
848 aop->size = getSize(sym->type);
849 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
850 pic16_allocDirReg( IC_LEFT(ic) );
855 /* only remaining is far space */
856 sym->aop = aop = newAsmop(AOP_PCODE);
858 /* change the next if to 1 to revert to good old immediate code */
859 if(IN_CODESPACE(space)) {
860 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
861 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
862 PCOI(aop->aopu.pcop)->index = 0;
864 /* try to allocate via direct register */
865 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
866 // aop->size = getSize( sym->type );
869 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
870 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
873 if(!pic16_allocDirReg (IC_LEFT(ic)))
877 if(IN_DIRSPACE( space ))
879 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
880 aop->size = FPTRSIZE;
881 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
882 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
883 else if(sym->onStack) {
886 if(SPEC_SCLS(sym->etype) == S_PDATA) {
887 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
888 aop->size = FPTRSIZE;
893 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
895 /* if it is in code space */
896 if (IN_CODESPACE(space))
902 /*-----------------------------------------------------------------*/
903 /* aopForRemat - rematerialzes an object */
904 /*-----------------------------------------------------------------*/
905 static asmop *aopForRemat (operand *op) // x symbol *sym)
907 symbol *sym = OP_SYMBOL(op);
909 iCode *ic = NULL, *oldic;
910 asmop *aop = newAsmop(AOP_PCODE);
917 ic = sym->rematiCode;
919 if(IS_OP_POINTER(op)) {
920 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
926 // pic16_emitpcomment("ic: %s\n", printILine(ic));
929 val += (int) operandLitValue(IC_RIGHT(ic));
930 } else if (ic->op == '-') {
931 val -= (int) operandLitValue(IC_RIGHT(ic));
935 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
938 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
941 if(!op->isaddr)viaimmd++; else viaimmd=0;
943 /* set the following if to 1 to revert to good old immediate code */
944 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
947 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
949 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
952 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
954 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
957 PCOI(aop->aopu.pcop)->index = val;
959 aop->size = getSize( sym->type );
961 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
963 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
964 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
966 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
970 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
971 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
973 val, IS_PTR_CONST(operandType(op)));
975 val, IS_CODEPTR(operandType(op)));
978 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
980 pic16_allocDirReg (IC_LEFT(ic));
982 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
989 static int aopIdx (asmop *aop, int offset)
994 if(aop->type != AOP_REG)
997 return aop->aopu.aop_reg[offset]->rIdx;
1002 /*-----------------------------------------------------------------*/
1003 /* regsInCommon - two operands have some registers in common */
1004 /*-----------------------------------------------------------------*/
1005 static bool regsInCommon (operand *op1, operand *op2)
1007 symbol *sym1, *sym2;
1010 /* if they have registers in common */
1011 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1014 sym1 = OP_SYMBOL(op1);
1015 sym2 = OP_SYMBOL(op2);
1017 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1020 for (i = 0 ; i < sym1->nRegs ; i++) {
1025 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1029 if (sym2->regs[j] == sym1->regs[i])
1037 /*-----------------------------------------------------------------*/
1038 /* operandsEqu - equivalent */
1039 /*-----------------------------------------------------------------*/
1040 static bool operandsEqu ( operand *op1, operand *op2)
1042 symbol *sym1, *sym2;
1044 /* if they not symbols */
1045 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1048 sym1 = OP_SYMBOL(op1);
1049 sym2 = OP_SYMBOL(op2);
1051 /* if both are itemps & one is spilt
1052 and the other is not then false */
1053 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1054 sym1->isspilt != sym2->isspilt )
1057 /* if they are the same */
1061 if (sym1->rname[0] && sym2->rname[0]
1062 && strcmp (sym1->rname, sym2->rname) == 0)
1066 /* if left is a tmp & right is not */
1067 if (IS_ITEMP(op1) &&
1070 (sym1->usl.spillLoc == sym2))
1073 if (IS_ITEMP(op2) &&
1077 (sym2->usl.spillLoc == sym1))
1083 /*-----------------------------------------------------------------*/
1084 /* pic16_sameRegs - two asmops have the same registers */
1085 /*-----------------------------------------------------------------*/
1086 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1093 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1094 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1096 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1098 if (aop1->type != AOP_REG ||
1099 aop2->type != AOP_REG )
1102 /* This is a bit too restrictive if one is a subset of the other...
1103 if (aop1->size != aop2->size )
1107 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1108 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1110 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1111 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1118 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1120 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1121 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1123 if(aop1 == aop2)return TRUE;
1124 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1126 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1132 /*-----------------------------------------------------------------*/
1133 /* pic16_aopOp - allocates an asmop for an operand : */
1134 /*-----------------------------------------------------------------*/
1135 void pic16_aopOp (operand *op, iCode *ic, bool result)
1144 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1146 /* if this a literal */
1147 if (IS_OP_LITERAL(op)) {
1148 op->aop = aop = newAsmop(AOP_LIT);
1149 aop->aopu.aop_lit = op->operand.valOperand;
1150 aop->size = getSize(operandType(op));
1155 sym_link *type = operandType(op);
1157 if(IS_PTR_CONST(type))
1159 if(IS_CODEPTR(type))
1161 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1164 /* if already has a asmop then continue */
1168 /* if the underlying symbol has a aop */
1169 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1170 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1171 op->aop = OP_SYMBOL(op)->aop;
1175 /* if this is a true symbol */
1176 if (IS_TRUE_SYMOP(op)) {
1177 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1178 op->aop = aopForSym(ic, op, result);
1182 /* this is a temporary : this has
1188 e) can be a return use only */
1190 sym = OP_SYMBOL(op);
1192 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1193 /* if the type is a conditional */
1194 if (sym->regType == REG_CND) {
1195 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1200 /* if it is spilt then two situations
1202 b) has a spill location */
1203 if (sym->isspilt || sym->nRegs == 0) {
1205 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1206 DEBUGpic16_emitcode(";","%d",__LINE__);
1207 /* rematerialize it NOW */
1210 sym->aop = op->aop = aop = aopForRemat (op);
1211 // aop->size = getSize(sym->type);
1212 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1219 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1220 aop->size = getSize(sym->type);
1221 for ( i = 0 ; i < 1 ; i++ ) {
1222 aop->aopu.aop_str[i] = accUse[i];
1223 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1225 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1226 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1234 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1235 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1236 //pic16_allocDirReg (IC_LEFT(ic));
1237 aop->size = getSize(sym->type);
1242 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1243 aop->size = getSize(sym->type);
1244 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1245 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1247 DEBUGpic16_emitcode(";","%d",__LINE__);
1251 /* else spill location */
1252 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1253 /* force a new aop if sizes differ */
1254 sym->usl.spillLoc->aop = NULL;
1258 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1259 __FUNCTION__,__LINE__,
1260 sym->usl.spillLoc->rname,
1261 sym->rname, sym->usl.spillLoc->offset);
1264 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1265 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1266 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1267 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1269 sym->usl.spillLoc->offset, op);
1271 fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1272 DEBUGpic16_emitcode (";","%s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1273 assert (getSize(sym->type) <= 1);
1274 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1276 aop->size = getSize(sym->type);
1282 sym_link *type = operandType(op);
1284 if(IS_PTR_CONST(type))
1286 if(IS_CODEPTR(type))
1288 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1291 /* must be in a register */
1292 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1293 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1294 aop->size = sym->nRegs;
1295 for ( i = 0 ; i < sym->nRegs ;i++)
1296 aop->aopu.aop_reg[i] = sym->regs[i];
1299 /*-----------------------------------------------------------------*/
1300 /* pic16_freeAsmop - free up the asmop given to an operand */
1301 /*----------------------------------------------------------------*/
1302 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1319 /* depending on the asmop type only three cases need work AOP_RO
1320 , AOP_R1 && AOP_STK */
1322 switch (aop->type) {
1324 if (_G.fsr0Pushed ) {
1326 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1327 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1328 // pic16_emitcode ("pop","ar0");
1332 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1336 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1342 pic16_emitcode ("pop","ar0");
1346 bitVectUnSetBit(ic->rUsed,R0_IDX);
1352 pic16_emitcode ("pop","ar1");
1356 bitVectUnSetBit(ic->rUsed,R1_IDX);
1363 /* we must store the result on stack */
1364 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1365 // operands on stack are accessible via "FSR2 + index" with index
1366 // starting at 2 for arguments and growing from 0 downwards for
1367 // local variables (index == 0 is not assigned so we add one here)
1368 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1373 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1374 for(i=0;i<aop->size;i++) {
1375 /* initialise for stack access via frame pointer */
1376 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1377 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1378 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1381 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1385 for(i=0;i<aop->size;i++) {
1386 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1388 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1389 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1400 int stk = aop->aopu.aop_stk + aop->size;
1401 bitVectUnSetBit(ic->rUsed,R0_IDX);
1402 bitVectUnSetBit(ic->rUsed,R1_IDX);
1404 getFreePtr(ic,&aop,FALSE);
1406 if (options.stack10bit)
1408 /* I'm not sure what to do here yet... */
1411 "*** Warning: probably generating bad code for "
1412 "10 bit stack mode.\n");
1416 pic16_emitcode ("mov","a,_bp");
1417 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1418 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1420 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1424 pic16_emitcode("pop","acc");
1425 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1427 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1430 pic16_freeAsmop(op,NULL,ic,TRUE);
1432 pic16_emitcode("pop","ar0");
1437 pic16_emitcode("pop","ar1");
1447 /* all other cases just dealloc */
1451 OP_SYMBOL(op)->aop = NULL;
1452 /* if the symbol has a spill */
1454 SPIL_LOC(op)->aop = NULL;
1459 /*-----------------------------------------------------------------*/
1460 /* pic16_aopGet - for fetching value of the aop */
1461 /*-----------------------------------------------------------------*/
1462 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1467 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1469 /* offset is greater than size then zero */
1470 if (offset > (aop->size - 1) &&
1471 aop->type != AOP_LIT)
1474 /* depending on type */
1475 switch (aop->type) {
1479 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1480 rs = Safe_calloc(1, strlen(s)+1);
1485 /* if we need to increment it */
1486 while (offset > aop->coff)
1488 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1492 while (offset < aop->coff)
1494 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1500 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1501 return (dname ? "acc" : "a");
1503 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1504 rs = Safe_calloc (1, strlen (s) + 1);
1512 sprintf (s,"%s",aop->aopu.aop_immd);
1515 sprintf(s,"(%s >> %d)",
1520 aop->aopu.aop_immd);
1521 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1522 rs = Safe_calloc(1,strlen(s)+1);
1528 sprintf(s,"(%s + %d)",
1531 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1533 sprintf(s,"%s",aop->aopu.aop_dir);
1534 rs = Safe_calloc(1,strlen(s)+1);
1540 // return aop->aopu.aop_reg[offset]->dname;
1542 return aop->aopu.aop_reg[offset]->name;
1545 //pic16_emitcode(";","%d",__LINE__);
1546 return aop->aopu.aop_dir;
1549 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1550 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1552 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1553 rs = Safe_strdup("WREG");
1557 sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1558 rs = Safe_calloc(1,strlen(s)+1);
1563 aop->coff = offset ;
1565 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1568 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1569 aop->type = AOP_ACC;
1570 return Safe_strdup("WREG");
1572 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1574 return aop->aopu.aop_str[offset];
1578 pCodeOp *pcop = aop->aopu.pcop;
1579 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1581 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1582 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1584 sprintf(s,"(%s + %d)", pcop->name, offset);
1586 sprintf(s,"%s", pcop->name);
1589 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1592 rs = Safe_calloc(1,strlen(s)+1);
1598 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1600 sprintf(s,"(%s + %d)",
1604 sprintf(s,"%s",aop->aopu.aop_dir);
1605 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1606 rs = Safe_calloc(1,strlen(s)+1);
1612 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1616 // pCodeOp *pcop = aop->aop
1621 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1622 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1623 "aopget got unsupported aop->type");
1629 /* lock has the following meaning: When allocating temporary registers
1630 * for stack variables storage, the value of the temporary register is
1631 * saved on stack. Its value is restored at the end. This procedure is
1632 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1633 * a possibility that before a call to pic16_aopOp, a temporary register
1634 * is allocated for a while and it is freed after some time, this will
1635 * mess the stack and values will not be restored properly. So use lock=1
1636 * to allocate temporary registers used internally by the programmer, and
1637 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1638 * to inform the compiler developer about a possible bug. This is an internal
1639 * feature for developing the compiler -- VR */
1641 int _TempReg_lock = 0;
1642 /*-----------------------------------------------------------------*/
1643 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1644 /*-----------------------------------------------------------------*/
1645 pCodeOp *pic16_popGetTempReg(int lock)
1650 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1652 // werror(W_POSSBUG2, __FILE__, __LINE__);
1655 _TempReg_lock += lock;
1660 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1661 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1662 PCOR(pcop)->r->wasUsed=1;
1663 PCOR(pcop)->r->isFree=0;
1665 /* push value on stack */
1666 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1674 /*-----------------------------------------------------------------*/
1675 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1676 /* is not part of f, but don't save if */
1678 /*-----------------------------------------------------------------*/
1679 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1685 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1688 // werror(W_POSSBUG2, __FILE__, __LINE__);
1691 _TempReg_lock += lock;
1696 i = bitVectFirstBit(f);
1699 /* bypass registers that are used by function */
1700 if(!bitVectBitValue(f, i)) {
1702 /* bypass registers that are already allocated for stack access */
1703 if(!bitVectBitValue(v, i)) {
1705 // debugf("getting register rIdx = %d\n", i);
1706 /* ok, get the operand */
1707 pcop = pic16_newpCodeOpReg( i );
1709 /* should never by NULL */
1710 assert( pcop != NULL );
1714 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1717 PCOR(pcop)->r->wasUsed=1;
1718 PCOR(pcop)->r->isFree=0;
1724 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1726 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1727 /* already used in previous steps, break */
1734 /* caller takes care of the following */
1735 // bitVectSetBit(v, i);
1738 /* push value on stack */
1739 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1740 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1756 /*-----------------------------------------------------------------*/
1757 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1758 /*-----------------------------------------------------------------*/
1759 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1761 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1763 _TempReg_lock -= lock;
1765 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1766 PCOR(pcop)->r->isFree = 1;
1768 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1771 /*-----------------------------------------------------------------*/
1772 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1773 /*-----------------------------------------------------------------*/
1774 pCodeOp *pic16_popGetLabel(unsigned int key)
1777 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1782 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1785 /*-----------------------------------------------------------------*/
1786 /* pic16_popCopyReg - copy a pcode operator */
1787 /*-----------------------------------------------------------------*/
1788 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1792 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1793 memcpy (pcor, pc, sizeof (pCodeOpReg));
1794 pcor->r->wasUsed = 1;
1796 //pcor->pcop.type = pc->pcop.type;
1798 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1799 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1801 pcor->pcop.name = NULL;
1804 //pcor->rIdx = pc->rIdx;
1805 //pcor->r->wasUsed=1;
1806 //pcor->instance = pc->instance;
1808 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1813 /*-----------------------------------------------------------------*/
1814 /* pic16_popGetLit - asm operator to pcode operator conversion */
1815 /*-----------------------------------------------------------------*/
1816 pCodeOp *pic16_popGetLit(int lit)
1818 return pic16_newpCodeOpLit(lit);
1821 /*-----------------------------------------------------------------*/
1822 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1823 /*-----------------------------------------------------------------*/
1824 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1826 return pic16_newpCodeOpLit2(lit, arg2);
1830 /*-----------------------------------------------------------------*/
1831 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1832 /*-----------------------------------------------------------------*/
1833 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1835 return pic16_newpCodeOpImmd(name, offset,index, 0);
1839 /*-----------------------------------------------------------------*/
1840 /* pic16_popGet - asm operator to pcode operator conversion */
1841 /*-----------------------------------------------------------------*/
1842 pCodeOp *pic16_popGetWithString(char *str)
1848 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1852 pcop = pic16_newpCodeOp(str,PO_STR);
1857 /*-----------------------------------------------------------------*/
1858 /* pic16_popRegFromString - */
1859 /*-----------------------------------------------------------------*/
1860 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1863 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1864 pcop->type = PO_DIR;
1866 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1867 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1872 pcop->name = Safe_calloc(1,strlen(str)+1);
1873 strcpy(pcop->name,str);
1875 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1877 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1879 /* make sure that register doesn't exist,
1880 * and operand isn't NULL
1881 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1882 if((PCOR(pcop)->r == NULL)
1884 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1885 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1886 // __FUNCTION__, __LINE__, str, size, offset);
1888 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1889 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1892 PCOR(pcop)->instance = offset;
1897 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1901 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1903 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1904 PCOR(pcop)->rIdx = rIdx;
1905 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1907 PCOR(pcop)->r->isFree = 0;
1908 PCOR(pcop)->r->wasUsed = 1;
1910 pcop->type = PCOR(pcop)->r->pc_type;
1915 /*---------------------------------------------------------------------------------*/
1916 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1918 /*---------------------------------------------------------------------------------*/
1919 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1924 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1926 /* comment the following check, so errors to throw up */
1927 // if(!pcop2)return NULL;
1929 temp = pic16_popGet(aop_dst, offset);
1930 pcop2->pcop2 = temp;
1937 /*--------------------------------------------------------------------------------.-*/
1938 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1939 /* VR 030601 , adapted by Hans Dorn */
1940 /*--------------------------------------------------------------------------------.-*/
1941 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1945 pcop2 = (pCodeOpReg2 *)src;
1953 /*---------------------------------------------------------------------------------*/
1954 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1955 /* movff instruction */
1956 /*---------------------------------------------------------------------------------*/
1957 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1962 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1963 pcop2->pcop2 = pic16_popCopyReg(dst);
1965 /* the pCodeOp may be already allocated */
1966 pcop2 = (pCodeOpReg2 *)(src);
1967 pcop2->pcop2 = (pCodeOp *)(dst);
1974 /*-----------------------------------------------------------------*/
1975 /* pic16_popGet - asm operator to pcode operator conversion */
1976 /*-----------------------------------------------------------------*/
1977 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1979 //char *s = buffer ;
1984 /* offset is greater than
1987 // if (offset > (aop->size - 1) &&
1988 // aop->type != AOP_LIT)
1989 // return NULL; //zero;
1991 /* depending on type */
1992 switch (aop->type) {
1998 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1999 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2006 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2007 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2008 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2009 PCOR(pcop)->r->wasUsed = 1;
2010 PCOR(pcop)->r->isFree = 0;
2012 PCOR(pcop)->instance = offset;
2013 pcop->type = PCOR(pcop)->r->pc_type;
2017 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2018 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2021 /* pCodeOp is already allocated from aopForSym */
2022 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2023 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2029 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2031 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2033 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2035 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2036 PCOR(pcop)->rIdx = rIdx;
2037 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2038 PCOR(pcop)->r->wasUsed=1;
2039 PCOR(pcop)->r->isFree=0;
2041 PCOR(pcop)->instance = offset;
2042 pcop->type = PCOR(pcop)->r->pc_type;
2043 // rs = aop->aopu.aop_reg[offset]->name;
2044 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2048 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2049 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2055 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2056 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2060 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2061 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2067 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2068 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2070 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2072 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2073 // pcop->type = PO_GPR_REGISTER;
2074 PCOR(pcop)->rIdx = rIdx;
2075 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2076 PCOR(pcop)->r->wasUsed=1;
2077 PCOR(pcop)->r->isFree=0;
2079 PCOR(pcop)->instance = offset;
2080 pcop->type = PCOR(pcop)->r->pc_type;
2082 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2083 rs = aop->aopu.aop_reg[offset]->name;
2084 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2089 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2091 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2092 PCOR(pcop)->instance = offset;
2093 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2094 //if(PCOR(pcop)->r == NULL)
2095 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2099 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2100 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2103 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2104 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2107 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2108 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2109 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2110 pcop->type = PCOR(pcop)->r->pc_type;
2111 pcop->name = PCOR(pcop)->r->name;
2117 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2119 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2120 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2121 switch( aop->aopu.pcop->type ) {
2122 case PO_DIR: PCOR(pcop)->instance += offset; break;
2123 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2128 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2129 assert( 0 ); /* should never reach here */;
2134 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2135 "pic16_popGet got unsupported aop->type");
2138 /*-----------------------------------------------------------------*/
2139 /* pic16_aopPut - puts a string for a aop */
2140 /*-----------------------------------------------------------------*/
2141 void pic16_aopPut (asmop *aop, char *s, int offset)
2148 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2150 if (aop->size && offset > ( aop->size - 1)) {
2151 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2152 "pic16_aopPut got offset > aop->size");
2156 /* will assign value to value */
2157 /* depending on where it is ofcourse */
2158 switch (aop->type) {
2161 sprintf(d,"(%s + %d)",
2162 aop->aopu.aop_dir,offset);
2163 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2166 sprintf(d,"%s",aop->aopu.aop_dir);
2169 DEBUGpic16_emitcode(";","%d",__LINE__);
2171 pic16_emitcode("movf","%s,w",s);
2172 pic16_emitcode("movwf","%s",d);
2175 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2176 if(offset >= aop->size) {
2177 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2180 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2183 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2190 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2191 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2194 strcmp(s,"r0") == 0 ||
2195 strcmp(s,"r1") == 0 ||
2196 strcmp(s,"r2") == 0 ||
2197 strcmp(s,"r3") == 0 ||
2198 strcmp(s,"r4") == 0 ||
2199 strcmp(s,"r5") == 0 ||
2200 strcmp(s,"r6") == 0 ||
2201 strcmp(s,"r7") == 0 )
2202 pic16_emitcode("mov","%s,%s ; %d",
2203 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2207 if(strcmp(s,"W")==0 )
2208 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2210 pic16_emitcode("movwf","%s",
2211 aop->aopu.aop_reg[offset]->name);
2213 if(strcmp(s,zero)==0) {
2214 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2216 } else if(strcmp(s,"W")==0) {
2217 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2218 pcop->type = PO_GPR_REGISTER;
2220 PCOR(pcop)->rIdx = -1;
2221 PCOR(pcop)->r = NULL;
2223 DEBUGpic16_emitcode(";","%d",__LINE__);
2224 pcop->name = Safe_strdup(s);
2225 pic16_emitpcode(POC_MOVFW,pcop);
2226 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2227 } else if(strcmp(s,one)==0) {
2228 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2229 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2231 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2239 if (aop->type == AOP_DPTR2)
2245 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2246 "pic16_aopPut writting to code space");
2250 while (offset > aop->coff) {
2252 pic16_emitcode ("inc","dptr");
2255 while (offset < aop->coff) {
2257 pic16_emitcode("lcall","__decdptr");
2262 /* if not in accumulater */
2265 pic16_emitcode ("movx","@dptr,a");
2267 if (aop->type == AOP_DPTR2)
2275 while (offset > aop->coff) {
2277 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2279 while (offset < aop->coff) {
2281 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2287 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2292 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2294 if (strcmp(s,"r0") == 0 ||
2295 strcmp(s,"r1") == 0 ||
2296 strcmp(s,"r2") == 0 ||
2297 strcmp(s,"r3") == 0 ||
2298 strcmp(s,"r4") == 0 ||
2299 strcmp(s,"r5") == 0 ||
2300 strcmp(s,"r6") == 0 ||
2301 strcmp(s,"r7") == 0 ) {
2303 sprintf(buffer,"a%s",s);
2304 pic16_emitcode("mov","@%s,%s",
2305 aop->aopu.aop_ptr->name,buffer);
2307 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2312 if (strcmp(s,"a") == 0)
2313 pic16_emitcode("push","acc");
2315 pic16_emitcode("push","%s",s);
2320 /* if bit variable */
2321 if (!aop->aopu.aop_dir) {
2322 pic16_emitcode("clr","a");
2323 pic16_emitcode("rlc","a");
2326 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2329 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2332 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2334 lbl = newiTempLabel(NULL);
2336 if (strcmp(s,"a")) {
2339 pic16_emitcode("clr","c");
2340 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2341 pic16_emitcode("cpl","c");
2342 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2343 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2350 if (strcmp(aop->aopu.aop_str[offset],s))
2351 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2356 if (!offset && (strcmp(s,"acc") == 0))
2359 if (strcmp(aop->aopu.aop_str[offset],s))
2360 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2364 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2365 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2366 // "pic16_aopPut got unsupported aop->type");
2372 /*-----------------------------------------------------------------*/
2373 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2374 /*-----------------------------------------------------------------*/
2375 void pic16_mov2w (asmop *aop, int offset)
2377 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2380 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2382 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2385 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2387 if(is_LitAOp(src)) {
2388 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2389 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2391 if(pic16_sameRegsOfs(src, dst, offset))return;
2392 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2393 pic16_popGet(dst, offset)));
2397 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2399 if(is_LitAOp(src)) {
2400 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2401 pic16_emitpcode(POC_MOVWF, dst);
2403 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2407 void pic16_testStackOverflow(void)
2409 #define GSTACK_TEST_NAME "_gstack_test"
2411 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2416 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2417 sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2418 // strcpy(sym->rname, GSTACK_TEST_NAME);
2419 checkAddSym(&externs, sym);
2424 /* push pcop into stack */
2425 void pic16_pushpCodeOp(pCodeOp *pcop)
2427 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2428 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2429 if(pic16_options.gstack)
2430 pic16_testStackOverflow();
2434 /* pop pcop from stack */
2435 void pic16_poppCodeOp(pCodeOp *pcop)
2437 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2438 if(pic16_options.gstack)
2439 pic16_testStackOverflow();
2443 /*-----------------------------------------------------------------*/
2444 /* pushw - pushes wreg to stack */
2445 /*-----------------------------------------------------------------*/
2448 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2449 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2450 if(pic16_options.gstack)
2451 pic16_testStackOverflow();
2455 /*-----------------------------------------------------------------*/
2456 /* pushaop - pushes aop to stack */
2457 /*-----------------------------------------------------------------*/
2458 void pushaop(asmop *aop, int offset)
2460 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2462 if(is_LitAOp(aop)) {
2463 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2464 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2466 pic16_emitpcode(POC_MOVFF,
2467 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2470 if(pic16_options.gstack)
2471 pic16_testStackOverflow();
2474 /*-----------------------------------------------------------------*/
2475 /* popaop - pops aop from stack */
2476 /*-----------------------------------------------------------------*/
2477 void popaop(asmop *aop, int offset)
2479 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2480 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2481 if(pic16_options.gstack)
2482 pic16_testStackOverflow();
2485 void popaopidx(asmop *aop, int offset, int index)
2489 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2491 if(STACK_MODEL_LARGE)ofs++;
2493 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2494 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2495 if(pic16_options.gstack)
2496 pic16_testStackOverflow();
2499 #if !(USE_GENERIC_SIGNED_SHIFT)
2500 /*-----------------------------------------------------------------*/
2501 /* reAdjustPreg - points a register back to where it should */
2502 /*-----------------------------------------------------------------*/
2503 static void reAdjustPreg (asmop *aop)
2507 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2509 if ((size = aop->size) <= 1)
2512 switch (aop->type) {
2516 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2520 if (aop->type == AOP_DPTR2)
2526 pic16_emitcode("lcall","__decdptr");
2529 if (aop->type == AOP_DPTR2)
2541 /*-----------------------------------------------------------------*/
2542 /* opIsGptr: returns non-zero if the passed operand is */
2543 /* a generic pointer type. */
2544 /*-----------------------------------------------------------------*/
2545 static int opIsGptr(operand *op)
2547 sym_link *type = operandType(op);
2549 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2550 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2558 /*-----------------------------------------------------------------*/
2559 /* pic16_getDataSize - get the operand data size */
2560 /*-----------------------------------------------------------------*/
2561 int pic16_getDataSize(operand *op)
2563 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2566 return AOP_SIZE(op);
2568 // tsd- in the pic port, the genptr size is 1, so this code here
2569 // fails. ( in the 8051 port, the size was 4).
2572 size = AOP_SIZE(op);
2573 if (size == GPTRSIZE)
2575 sym_link *type = operandType(op);
2576 if (IS_GENPTR(type))
2578 /* generic pointer; arithmetic operations
2579 * should ignore the high byte (pointer type).
2582 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2589 /*-----------------------------------------------------------------*/
2590 /* pic16_outAcc - output Acc */
2591 /*-----------------------------------------------------------------*/
2592 void pic16_outAcc(operand *result)
2595 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2596 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2599 size = pic16_getDataSize(result);
2601 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2604 /* unsigned or positive */
2606 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2611 /*-----------------------------------------------------------------*/
2612 /* pic16_outBitC - output a bit C */
2613 /* Move to result the value of Carry flag -- VR */
2614 /*-----------------------------------------------------------------*/
2615 void pic16_outBitC(operand *result)
2619 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2621 /* if the result is bit */
2622 if (AOP_TYPE(result) == AOP_CRY) {
2623 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2624 pic16_aopPut(AOP(result),"c",0);
2627 i = AOP_SIZE(result);
2629 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2631 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2635 /*-----------------------------------------------------------------*/
2636 /* pic16_outBitOp - output a bit from Op */
2637 /* Move to result the value of set/clr op -- VR */
2638 /*-----------------------------------------------------------------*/
2639 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2643 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2645 /* if the result is bit */
2646 if (AOP_TYPE(result) == AOP_CRY) {
2647 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2648 pic16_aopPut(AOP(result),"c",0);
2651 i = AOP_SIZE(result);
2653 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2655 pic16_emitpcode(POC_RRCF, pcop);
2656 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2660 /*-----------------------------------------------------------------*/
2661 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2662 /*-----------------------------------------------------------------*/
2663 void pic16_toBoolean(operand *oper)
2665 int size = AOP_SIZE(oper) - 1;
2668 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2670 if ( AOP_TYPE(oper) != AOP_ACC) {
2671 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2674 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2679 #if !defined(GEN_Not)
2680 /*-----------------------------------------------------------------*/
2681 /* genNot - generate code for ! operation */
2682 /*-----------------------------------------------------------------*/
2683 static void pic16_genNot (iCode *ic)
2689 /* assign asmOps to operand & result */
2690 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2691 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2693 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2694 /* if in bit space then a special case */
2695 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2696 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2697 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2698 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2700 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2701 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2702 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2707 size = AOP_SIZE(IC_LEFT(ic));
2709 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2710 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2711 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2714 pic16_toBoolean(IC_LEFT(ic));
2716 tlbl = newiTempLabel(NULL);
2717 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2718 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2719 pic16_outBitC(IC_RESULT(ic));
2722 /* release the aops */
2723 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2724 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2729 #if !defined(GEN_Cpl)
2730 /*-----------------------------------------------------------------*/
2731 /* genCpl - generate code for complement */
2732 /*-----------------------------------------------------------------*/
2733 static void pic16_genCpl (iCode *ic)
2739 /* assign asmOps to operand & result */
2740 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2741 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2743 /* if both are in bit space then
2745 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2746 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2748 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2749 pic16_emitcode("cpl","c");
2750 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2754 size = AOP_SIZE(IC_RESULT(ic));
2757 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2759 pic16_emitcode("cpl","a");
2760 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2762 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2763 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2765 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2766 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2774 /* release the aops */
2775 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2776 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2780 /*-----------------------------------------------------------------*/
2781 /* genUminusFloat - unary minus for floating points */
2782 /*-----------------------------------------------------------------*/
2783 static void genUminusFloat(operand *op,operand *result)
2785 int size ,offset =0 ;
2788 /* for this we just need to flip the
2789 first it then copy the rest in place */
2790 size = AOP_SIZE(op);
2793 pic16_mov2f(AOP(result), AOP(op), offset);
2797 /* toggle the MSB's highest bit */
2798 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2801 /*-----------------------------------------------------------------*/
2802 /* genUminus - unary minus code generation */
2803 /*-----------------------------------------------------------------*/
2804 static void genUminus (iCode *ic)
2807 sym_link *optype, *rtype;
2814 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2815 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2817 /* if both in bit space then special case */
2818 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2819 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2821 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2822 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2823 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2827 optype = operandType(IC_LEFT(ic));
2828 rtype = operandType(IC_RESULT(ic));
2830 /* if float then do float stuff */
2831 if (IS_FLOAT(optype)) {
2832 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2836 /* otherwise subtract from zero by taking the 2's complement */
2837 size = AOP_SIZE(IC_LEFT(ic));
2838 label = newiTempLabel ( NULL );
2840 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2841 for (i=size-1; i > 0; i--) {
2842 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2844 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2845 for (i=1; i < size; i++) {
2846 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2847 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2850 for (i=size-1; i >= 0; i--) {
2851 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2852 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2855 for (i=0; i < size-2; i++) {
2856 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2857 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2859 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2861 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2864 pic16_emitpLabel (label->key);
2867 /* release the aops */
2868 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2869 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2873 /*-----------------------------------------------------------------*/
2874 /* saveRegisters - will look for a call and save the registers */
2875 /*-----------------------------------------------------------------*/
2876 static void saveRegisters(iCode *lic)
2883 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2885 for (ic = lic ; ic ; ic = ic->next)
2886 if (ic->op == CALL || ic->op == PCALL)
2890 fprintf(stderr,"found parameter push with no function call\n");
2894 /* if the registers have been saved already then
2896 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2899 /* find the registers in use at this time
2900 and push them away to safety */
2901 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2905 if (options.useXstack) {
2906 if (bitVectBitValue(rsave,R0_IDX))
2907 pic16_emitcode("mov","b,r0");
2908 pic16_emitcode("mov","r0,%s",spname);
2909 for (i = 0 ; i < pic16_nRegs ; i++) {
2910 if (bitVectBitValue(rsave,i)) {
2912 pic16_emitcode("mov","a,b");
2914 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2915 pic16_emitcode("movx","@r0,a");
2916 pic16_emitcode("inc","r0");
2919 pic16_emitcode("mov","%s,r0",spname);
2920 if (bitVectBitValue(rsave,R0_IDX))
2921 pic16_emitcode("mov","r0,b");
2923 //for (i = 0 ; i < pic16_nRegs ; i++) {
2924 // if (bitVectBitValue(rsave,i))
2925 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2928 dtype = operandType(IC_LEFT(ic));
2929 if (currFunc && dtype &&
2930 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2931 IFFUNC_ISISR(currFunc->type) &&
2934 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2937 /*-----------------------------------------------------------------*/
2938 /* unsaveRegisters - pop the pushed registers */
2939 /*-----------------------------------------------------------------*/
2940 static void unsaveRegisters (iCode *ic)
2945 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2946 /* find the registers in use at this time
2947 and push them away to safety */
2948 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2951 if (options.useXstack) {
2952 pic16_emitcode("mov","r0,%s",spname);
2953 for (i = pic16_nRegs ; i >= 0 ; i--) {
2954 if (bitVectBitValue(rsave,i)) {
2955 pic16_emitcode("dec","r0");
2956 pic16_emitcode("movx","a,@r0");
2958 pic16_emitcode("mov","b,a");
2960 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2964 pic16_emitcode("mov","%s,r0",spname);
2965 if (bitVectBitValue(rsave,R0_IDX))
2966 pic16_emitcode("mov","r0,b");
2968 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2969 // if (bitVectBitValue(rsave,i))
2970 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2977 /*-----------------------------------------------------------------*/
2979 /*-----------------------------------------------------------------*/
2980 static void pushSide(operand * oper, int size)
2983 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2985 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2986 if (AOP_TYPE(oper) != AOP_REG &&
2987 AOP_TYPE(oper) != AOP_DIR &&
2989 pic16_emitcode("mov","a,%s",l);
2990 pic16_emitcode("push","acc");
2992 pic16_emitcode("push","%s",l);
2997 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2999 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3000 pic16_emitpcode(POC_MOVFW, src);
3001 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
3003 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3004 src, pic16_popGet(AOP(op), offset)));
3009 /*-----------------------------------------------------------------*/
3010 /* assignResultValue - assign results to oper, rescall==1 is */
3011 /* called from genCall() or genPcall() */
3012 /*-----------------------------------------------------------------*/
3013 static void assignResultValue(operand * oper, int rescall)
3015 int size = AOP_SIZE(oper);
3019 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3020 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3023 /* assign result from a call/pcall function() */
3025 /* function results are stored in a special order,
3026 * see top of file with Function return policy, or manual */
3029 /* 8-bits, result in WREG */
3030 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3033 /* 16-bits, result in PRODL:WREG */
3034 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3038 /* 24-bits, result in PRODH:PRODL:WREG */
3039 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3043 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3044 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3048 /* >32-bits, result on stack, and FSR0 points to beginning.
3049 * Fix stack when done */
3051 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3053 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3054 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3056 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3061 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3062 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3063 if(STACK_MODEL_LARGE) {
3065 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3069 int areg = 0; /* matching argument register */
3071 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3072 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3075 /* its called from genReceive (probably) -- VR */
3076 /* I hope this code will not be called from somewhere else in the future!
3077 * We manually set the pseudo stack pointer in genReceive. - dw
3079 if(!GpsuedoStkPtr && _G.useWreg) {
3080 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3082 /* The last byte in the assignment is in W */
3083 if(areg <= GpsuedoStkPtr) {
3085 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3087 // debugf("receive from WREG\n", 0);
3089 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3092 _G.stack_lat = AOP_SIZE(oper)-1;
3097 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3098 // debugf("receive from STACK\n", 0);
3105 /*-----------------------------------------------------------------*/
3106 /* genIpush - generate code for pushing this gets a little complex */
3107 /*-----------------------------------------------------------------*/
3108 static void genIpush (iCode *ic)
3110 // int size, offset=0;
3113 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3116 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3118 /* send to stack as normal */
3119 addSet(&_G.sendSet,ic);
3120 // addSetHead(&_G.sendSet,ic);
3121 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3126 int size, offset = 0 ;
3130 /* if this is not a parm push : ie. it is spill push
3131 and spill push is always done on the local stack */
3132 if (!ic->parmPush) {
3134 /* and the item is spilt then do nothing */
3135 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3138 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3139 size = AOP_SIZE(IC_LEFT(ic));
3140 /* push it on the stack */
3142 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3147 pic16_emitcode("push","%s",l);
3152 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3156 /*-----------------------------------------------------------------*/
3157 /* genIpop - recover the registers: can happen only for spilling */
3158 /*-----------------------------------------------------------------*/
3159 static void genIpop (iCode *ic)
3162 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3167 /* if the temp was not pushed then */
3168 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3171 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3172 size = AOP_SIZE(IC_LEFT(ic));
3175 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3178 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3183 /*-----------------------------------------------------------------*/
3184 /* unsaverbank - restores the resgister bank from stack */
3185 /*-----------------------------------------------------------------*/
3186 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3188 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3194 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3196 if (options.useXstack) {
3198 r = getFreePtr(ic,&aop,FALSE);
3201 pic16_emitcode("mov","%s,_spx",r->name);
3202 pic16_emitcode("movx","a,@%s",r->name);
3203 pic16_emitcode("mov","psw,a");
3204 pic16_emitcode("dec","%s",r->name);
3207 pic16_emitcode ("pop","psw");
3210 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3211 if (options.useXstack) {
3212 pic16_emitcode("movx","a,@%s",r->name);
3213 //pic16_emitcode("mov","(%s+%d),a",
3214 // regspic16[i].base,8*bank+regspic16[i].offset);
3215 pic16_emitcode("dec","%s",r->name);
3218 pic16_emitcode("pop",""); //"(%s+%d)",
3219 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3222 if (options.useXstack) {
3224 pic16_emitcode("mov","_spx,%s",r->name);
3225 pic16_freeAsmop(NULL,aop,ic,TRUE);
3231 /*-----------------------------------------------------------------*/
3232 /* saverbank - saves an entire register bank on the stack */
3233 /*-----------------------------------------------------------------*/
3234 static void saverbank (int bank, iCode *ic, bool pushPsw)
3236 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3242 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3243 if (options.useXstack) {
3246 r = getFreePtr(ic,&aop,FALSE);
3247 pic16_emitcode("mov","%s,_spx",r->name);
3251 for (i = 0 ; i < pic16_nRegs ;i++) {
3252 if (options.useXstack) {
3253 pic16_emitcode("inc","%s",r->name);
3254 //pic16_emitcode("mov","a,(%s+%d)",
3255 // regspic16[i].base,8*bank+regspic16[i].offset);
3256 pic16_emitcode("movx","@%s,a",r->name);
3258 pic16_emitcode("push","");// "(%s+%d)",
3259 //regspic16[i].base,8*bank+regspic16[i].offset);
3263 if (options.useXstack) {
3264 pic16_emitcode("mov","a,psw");
3265 pic16_emitcode("movx","@%s,a",r->name);
3266 pic16_emitcode("inc","%s",r->name);
3267 pic16_emitcode("mov","_spx,%s",r->name);
3268 pic16_freeAsmop (NULL,aop,ic,TRUE);
3271 pic16_emitcode("push","psw");
3273 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3281 static int wparamCmp(void *p1, void *p2)
3283 return (!strcmp((char *)p1, (char *)p2));
3286 int inWparamList(char *s)
3288 return isinSetWith(wparamList, s, wparamCmp);
3292 /*-----------------------------------------------------------------*/
3293 /* genCall - generates a call statement */
3294 /*-----------------------------------------------------------------*/
3295 static void genCall (iCode *ic)
3305 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3306 /* if caller saves & we have not saved then */
3307 // if (!ic->regsSaved)
3308 // saveRegisters(ic);
3310 /* initialise stackParms for IPUSH pushes */
3311 // stackParms = psuedoStkPtr;
3312 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3313 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3314 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3317 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3320 /* if send set is not empty the assign */
3323 int psuedoStkPtr=-1;
3324 int firstTimeThruLoop = 1;
3327 /* reverse sendSet if function is not reentrant */
3328 if(!IFFUNC_ISREENT(ftype))
3329 _G.sendSet = reverseSet(_G.sendSet);
3331 /* First figure how many parameters are getting passed */
3335 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3339 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3340 size = AOP_SIZE(IC_LEFT(sic));
3344 /* pass the last byte through WREG */
3348 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3349 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3350 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3352 if(!firstTimeThruLoop) {
3353 /* If this is not the first time we've been through the loop
3354 * then we need to save the parameter in a temporary
3355 * register. The last byte of the last parameter is
3359 // --psuedoStkPtr; // sanity check
3363 firstTimeThruLoop=0;
3365 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3370 /* all arguments are passed via stack */
3374 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3375 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3376 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3378 // pushaop(AOP(IC_LEFT(sic)), size);
3379 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3386 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3390 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3391 pushw(); /* save last parameter to stack if functions has varargs */
3395 } else use_wreg = 0;
3397 _G.stackRegSet = _G.sendSet;
3402 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3406 /* if we need to assign a result value */
3407 if ((IS_ITEMP(IC_RESULT(ic))
3408 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3409 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3410 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3413 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3416 assignResultValue(IC_RESULT(ic), 1);
3418 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3419 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3421 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3424 if(!stackParms && ic->parmBytes) {
3425 stackParms = ic->parmBytes;
3428 stackParms -= use_wreg;
3431 if(stackParms == 1) {
3432 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3434 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3435 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3437 if(STACK_MODEL_LARGE) {
3439 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3444 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3447 /* adjust the stack for parameters if required */
3448 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3451 /* if register bank was saved then pop them */
3453 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3455 /* if we hade saved some registers then unsave them */
3456 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3457 unsaveRegisters (ic);
3463 /*-----------------------------------------------------------------*/
3464 /* genPcall - generates a call by pointer statement */
3465 /* new version, created from genCall - HJD */
3466 /*-----------------------------------------------------------------*/
3467 static void genPcall (iCode *ic)
3469 sym_link *ftype, *fntype;
3471 symbol *retlbl = newiTempLabel(NULL);
3472 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3476 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3477 fntype = operandType( IC_LEFT(ic) )->next;
3479 /* if send set is not empty the assign */
3482 int psuedoStkPtr=-1;
3484 /* reverse sendSet if function is not reentrant */
3485 if(!IFFUNC_ISREENT(fntype))
3486 _G.sendSet = reverseSet(_G.sendSet);
3490 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3493 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3494 size = AOP_SIZE(IC_LEFT(sic));
3497 /* all parameters are passed via stack, since WREG is clobbered
3498 * by the calling sequence */
3500 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3501 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3502 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3504 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3508 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3511 _G.stackRegSet = _G.sendSet;
3515 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3517 // push return address
3518 // push $ on return stack, then replace with retlbl
3520 /* Thanks to Thorsten Klose for pointing out that the following
3521 * snippet should be interrupt safe */
3522 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3523 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3525 pic16_emitpcodeNULLop(POC_PUSH);
3527 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3528 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3529 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3530 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3531 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3532 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3535 /* restore interrupt control register */
3536 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3537 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3539 /* make the call by writing the pointer into pc */
3540 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3541 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3543 // note: MOVFF to PCL not allowed
3544 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3545 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3548 /* return address is here: (X) */
3549 pic16_emitpLabelFORCE(retlbl->key);
3551 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3554 /* if we need assign a result value */
3555 if ((IS_ITEMP(IC_RESULT(ic))
3556 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3557 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3558 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3561 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3564 assignResultValue(IC_RESULT(ic), 1);
3566 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3567 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3569 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3572 // stackParms -= use_wreg;
3575 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3576 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3577 if(STACK_MODEL_LARGE) {
3579 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3584 /*-----------------------------------------------------------------*/
3585 /* resultRemat - result is rematerializable */
3586 /*-----------------------------------------------------------------*/
3587 static int resultRemat (iCode *ic)
3589 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3590 if (SKIP_IC(ic) || ic->op == IFX)
3593 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3594 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3595 if (sym->remat && !POINTER_SET(ic))
3602 #if defined(__BORLANDC__) || defined(_MSC_VER)
3603 #define STRCASECMP stricmp
3605 #define STRCASECMP strcasecmp
3609 /*-----------------------------------------------------------------*/
3610 /* inExcludeList - return 1 if the string is in exclude Reg list */
3611 /*-----------------------------------------------------------------*/
3612 static bool inExcludeList(char *s)
3614 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3617 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3618 if (options.excludeRegs[i] &&
3619 STRCASECMP(options.excludeRegs[i],"none") == 0)
3622 for ( i = 0 ; options.excludeRegs[i]; i++) {
3623 if (options.excludeRegs[i] &&
3624 STRCASECMP(s,options.excludeRegs[i]) == 0)
3631 /*-----------------------------------------------------------------*/
3632 /* genFunction - generated code for function entry */
3633 /*-----------------------------------------------------------------*/
3634 static void genFunction (iCode *ic)
3640 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3642 pic16_labelOffset += (max_key+4);
3647 ftype = operandType(IC_LEFT(ic));
3648 sym = OP_SYMBOL(IC_LEFT(ic));
3650 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3651 /* create an absolute section at the interrupt vector:
3652 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3657 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3659 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3660 sprintf(asymname, "ivec_%s", sym->name);
3662 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3664 /* when an interrupt is declared as naked, do not emit the special
3665 * wrapper segment at vector address. The user should take care for
3666 * this instead. -- VR */
3668 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3669 asym = newSymbol(asymname, 0);
3670 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3671 pic16_addpBlock( apb );
3673 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3674 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3675 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3676 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3677 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3679 /* mark the end of this tiny function */
3680 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3682 sprintf(asymname, "%s", sym->rname);
3688 abSym = Safe_calloc(1, sizeof(absSym));
3689 strcpy(abSym->name, asymname);
3691 switch( FUNC_INTNO(sym->type) ) {
3692 case 0: abSym->address = 0x000000; break;
3693 case 1: abSym->address = 0x000008; break;
3694 case 2: abSym->address = 0x000018; break;
3697 // fprintf(stderr, "no interrupt number is given\n");
3698 abSym->address = -1; break;
3701 /* relocate interrupt vectors if needed */
3702 if(abSym->address != -1)
3703 abSym->address += pic16_options.ivt_loc;
3705 addSet(&absSymSet, abSym);
3709 /* create the function header */
3710 pic16_emitcode(";","-----------------------------------------");
3711 pic16_emitcode(";"," function %s",sym->name);
3712 pic16_emitcode(";","-----------------------------------------");
3714 pic16_emitcode("","%s:",sym->rname);
3715 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3720 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3721 if(!strcmp(ab->name, sym->rname)) {
3722 pic16_pBlockConvert2Absolute(pb);
3728 if(IFFUNC_ISNAKED(ftype)) {
3729 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3733 /* if critical function then turn interrupts off */
3734 if (IFFUNC_ISCRITICAL(ftype)) {
3735 //pic16_emitcode("clr","ea");
3738 currFunc = sym; /* update the currFunc symbol */
3739 _G.fregsUsed = sym->regsUsed;
3740 _G.sregsAlloc = newBitVect(128);
3743 /* if this is an interrupt service routine then
3744 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3745 if (IFFUNC_ISISR(sym->type)) {
3746 _G.usefastretfie = 1; /* use shadow registers by default */
3748 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3749 if(!FUNC_ISSHADOWREGS(sym->type)) {
3750 /* do not save WREG,STATUS,BSR for high priority interrupts
3751 * because they are stored in the hardware shadow registers already */
3752 _G.usefastretfie = 0;
3753 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3754 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3755 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3758 /* these should really be optimized somehow, because not all
3759 * interrupt handlers modify them */
3760 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3761 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3762 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3763 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3765 // pic16_pBlockConvert2ISR(pb);
3768 /* emit code to setup stack frame if user enabled,
3769 * and function is not main() */
3771 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3772 if(strcmp(sym->name, "main")) {
3774 || !options.ommitFramePtr
3776 || IFFUNC_ARGS(sym->type)
3777 || FUNC_HASSTACKPARM(sym->etype)
3779 /* setup the stack frame */
3780 if(STACK_MODEL_LARGE)
3781 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3782 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3784 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3785 if(STACK_MODEL_LARGE)
3786 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3790 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3793 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3795 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3796 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3798 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3801 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3802 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3809 /* if callee-save to be used for this function
3810 * then save the registers being used in this function */
3811 // if (IFFUNC_CALLEESAVES(sym->type))
3815 /* if any registers used */
3816 if (sym->regsUsed) {
3817 /* save the registers used */
3818 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3819 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3820 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3821 if (bitVectBitValue(sym->regsUsed,i)) {
3822 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3825 if(!pic16_regWithIdx(i)->wasUsed) {
3826 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3827 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3828 pic16_regWithIdx(i)->wasUsed = 1;
3832 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3836 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3837 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3840 /*-----------------------------------------------------------------*/
3841 /* genEndFunction - generates epilogue for functions */
3842 /*-----------------------------------------------------------------*/
3843 static void genEndFunction (iCode *ic)
3845 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3849 if(IFFUNC_ISNAKED(sym->type)) {
3850 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3856 /* add code for ISCRITICAL */
3857 if(IFFUNC_ISCRITICAL(sym->type)) {
3858 /* if critical function, turn on interrupts */
3860 /* TODO: add code here -- VR */
3863 // sym->regsUsed = _G.fregsUsed;
3865 /* now we need to restore the registers */
3866 /* if any registers used */
3868 /* first restore registers that might be used for stack access */
3869 if(_G.sregsAllocSet) {
3872 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3873 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3874 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3878 if (sym->regsUsed) {
3881 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3882 /* restore registers used */
3883 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3884 for ( i = sym->regsUsed->size; i >= 0; i--) {
3885 if (bitVectBitValue(sym->regsUsed,i)) {
3886 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3890 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3895 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3897 if (sym->stack == 1) {
3898 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3899 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3901 // we have to add more than one...
3902 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3903 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3904 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3906 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3907 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3908 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3912 if(strcmp(sym->name, "main")) {
3914 || !options.ommitFramePtr
3916 || IFFUNC_ARGS(sym->type)
3917 || FUNC_HASSTACKPARM(sym->etype)
3919 /* restore stack frame */
3920 if(STACK_MODEL_LARGE)
3921 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3922 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3928 if (IFFUNC_ISISR(sym->type)) {
3929 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3930 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3931 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3932 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3934 if(!FUNC_ISSHADOWREGS(sym->type)) {
3935 /* do not restore interrupt vector for WREG,STATUS,BSR
3936 * for high priority interrupt, see genFunction */
3937 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3938 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3939 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3941 // _G.interruptvector = 0; /* sanity check */
3944 /* if debug then send end of function */
3945 /* if (options.debug && currFunc) */
3947 debugFile->writeEndFunction (currFunc, ic, 1);
3950 if(_G.usefastretfie)
3951 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3953 pic16_emitpcodeNULLop(POC_RETFIE);
3955 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3957 _G.usefastretfie = 0;
3961 if (IFFUNC_ISCRITICAL(sym->type)) {
3962 pic16_emitcode("setb","ea");
3965 /* if debug then send end of function */
3967 debugFile->writeEndFunction (currFunc, ic, 1);
3970 /* insert code to restore stack frame, if user enabled it
3971 * and function is not main() */
3974 pic16_emitpcodeNULLop(POC_RETURN);
3976 /* Mark the end of a function */
3977 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3981 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3983 unsigned long lit=1;
3988 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3989 if(AOP_TYPE(op) == AOP_LIT) {
3990 if(!IS_FLOAT(operandType( op ))) {
3991 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3994 unsigned long lit_int;
3998 /* take care if literal is a float */
3999 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4005 if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
4006 pic16_emitpcode(POC_CLRF, dest);
4008 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
4009 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
4012 if(dest->type == PO_WREG && (offset == 0)) {
4013 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4016 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4020 /*-----------------------------------------------------------------*/
4021 /* genRet - generate code for return statement */
4022 /*-----------------------------------------------------------------*/
4023 static void genRet (iCode *ic)
4029 /* if we have no return value then
4030 * just generate the "ret" */
4035 /* we have something to return then
4036 * move the return value into place */
4037 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4038 size = AOP_SIZE(IC_LEFT(ic));
4042 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4045 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4048 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4050 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4053 /* >32-bits, setup stack and FSR0 */
4055 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4056 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4058 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4060 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4065 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4066 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4068 if(STACK_MODEL_LARGE) {
4069 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4070 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4072 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4077 /* old code, left here for reference -- VR */
4081 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4083 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4084 pic16_emitpcomment("push %s",l);
4087 DEBUGpic16_emitcode(";", "%d", __LINE__);
4088 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4089 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4091 if (strcmp(fReturn[offset],l)) {
4092 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4093 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4094 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4096 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4100 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4110 if (strcmp(fReturn[pushed],"a"))
4111 pic16_emitcode("pop",fReturn[pushed]);
4113 pic16_emitcode("pop","acc");
4119 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4122 /* generate a jump to the return label
4123 * if the next is not the return statement */
4124 if (!(ic->next && ic->next->op == LABEL
4125 && IC_LABEL(ic->next) == returnLabel)) {
4127 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4128 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4132 /*-----------------------------------------------------------------*/
4133 /* genLabel - generates a label */
4134 /*-----------------------------------------------------------------*/
4135 static void genLabel (iCode *ic)
4139 /* special case never generate */
4140 if (IC_LABEL(ic) == entryLabel)
4143 pic16_emitpLabel(IC_LABEL(ic)->key);
4144 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4147 /*-----------------------------------------------------------------*/
4148 /* genGoto - generates a goto */
4149 /*-----------------------------------------------------------------*/
4151 static void genGoto (iCode *ic)
4154 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4155 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4159 /*-----------------------------------------------------------------*/
4160 /* genMultbits :- multiplication of bits */
4161 /*-----------------------------------------------------------------*/
4162 static void genMultbits (operand *left,
4168 if(!pic16_sameRegs(AOP(result),AOP(right)))
4169 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4171 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4172 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4173 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4178 /*-----------------------------------------------------------------*/
4179 /* genMultOneByte : 8 bit multiplication & division */
4180 /*-----------------------------------------------------------------*/
4181 static void genMultOneByte (operand *left,
4187 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4188 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4190 /* (if two literals, the value is computed before) */
4191 /* if one literal, literal on the right */
4192 if (AOP_TYPE(left) == AOP_LIT){
4198 /* size is already checked in genMult == 1 */
4199 // size = AOP_SIZE(result);
4201 if (AOP_TYPE(right) == AOP_LIT){
4202 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4203 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4204 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4205 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4207 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4208 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4209 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4210 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4213 pic16_genMult8X8_8 (left, right,result);
4216 /*-----------------------------------------------------------------*/
4217 /* genMultOneWord : 16 bit multiplication */
4218 /*-----------------------------------------------------------------*/
4219 static void genMultOneWord (operand *left,
4224 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4225 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4227 /* (if two literals, the value is computed before)
4228 * if one literal, literal on the right */
4229 if (AOP_TYPE(left) == AOP_LIT){
4235 /* size is checked already == 2 */
4236 // size = AOP_SIZE(result);
4238 if (AOP_TYPE(right) == AOP_LIT) {
4239 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4240 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4241 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4242 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4244 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4245 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4246 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4247 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4250 pic16_genMult16X16_16(left, right,result);
4253 /*-----------------------------------------------------------------*/
4254 /* genMultOneLong : 32 bit multiplication */
4255 /*-----------------------------------------------------------------*/
4256 static void genMultOneLong (operand *left,
4261 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4262 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4264 /* (if two literals, the value is computed before)
4265 * if one literal, literal on the right */
4266 if (AOP_TYPE(left) == AOP_LIT){
4272 /* size is checked already == 4 */
4273 // size = AOP_SIZE(result);
4275 if (AOP_TYPE(right) == AOP_LIT) {
4276 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4277 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4278 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4279 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4281 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4282 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4283 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4284 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4287 pic16_genMult32X32_32(left, right,result);
4292 /*-----------------------------------------------------------------*/
4293 /* genMult - generates code for multiplication */
4294 /*-----------------------------------------------------------------*/
4295 static void genMult (iCode *ic)
4297 operand *left = IC_LEFT(ic);
4298 operand *right = IC_RIGHT(ic);
4299 operand *result= IC_RESULT(ic);
4302 /* assign the amsops */
4303 pic16_aopOp (left,ic,FALSE);
4304 pic16_aopOp (right,ic,FALSE);
4305 pic16_aopOp (result,ic,TRUE);
4307 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4309 /* special cases first *
4311 if (AOP_TYPE(left) == AOP_CRY
4312 && AOP_TYPE(right)== AOP_CRY) {
4313 genMultbits(left,right,result);
4317 /* if both are of size == 1 */
4318 if(AOP_SIZE(left) == 1
4319 && AOP_SIZE(right) == 1) {
4320 genMultOneByte(left,right,result);
4324 /* if both are of size == 2 */
4325 if(AOP_SIZE(left) == 2
4326 && AOP_SIZE(right) == 2) {
4327 genMultOneWord(left, right, result);
4331 /* if both are of size == 4 */
4332 if(AOP_SIZE(left) == 4
4333 && AOP_SIZE(right) == 4) {
4334 genMultOneLong(left, right, result);
4338 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4341 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4342 /* should have been converted to function call */
4346 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4347 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4348 pic16_freeAsmop(result,NULL,ic,TRUE);
4351 /*-----------------------------------------------------------------*/
4352 /* genDivbits :- division of bits */
4353 /*-----------------------------------------------------------------*/
4354 static void genDivbits (operand *left,
4361 /* the result must be bit */
4362 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4363 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4367 pic16_emitcode("div","ab");
4368 pic16_emitcode("rrc","a");
4369 pic16_aopPut(AOP(result),"c",0);
4372 /*-----------------------------------------------------------------*/
4373 /* genDivOneByte : 8 bit division */
4374 /*-----------------------------------------------------------------*/
4375 static void genDivOneByte (operand *left,
4379 sym_link *opetype = operandType(result);
4384 /* result = divident / divisor
4385 * - divident may be a register or a literal,
4386 * - divisor may be a register or a literal,
4387 * so there are 3 cases (literal / literal is optimized
4388 * by the front-end) to handle.
4389 * In addition we must handle signed and unsigned, which
4390 * result in 6 final different cases -- VR */
4394 size = AOP_SIZE(result) - 1;
4396 /* signed or unsigned */
4397 if (SPEC_USIGN(opetype)) {
4398 pCodeOp *pct1, /* count */
4401 symbol *label1, *label2, *label3;;
4404 /* unsigned is easy */
4406 pct1 = pic16_popGetTempReg(1);
4407 pct2 = pic16_popGetTempReg(1);
4408 pct3 = pic16_popGetTempReg(1);
4410 label1 = newiTempLabel(NULL);
4411 label2 = newiTempLabel(NULL);
4412 label3 = newiTempLabel(NULL);
4414 /* the following algorithm is extracted from divuint.c */
4416 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4417 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4419 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4421 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4423 pic16_emitpLabel(label1->key);
4426 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4430 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4434 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4436 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4437 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4439 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4440 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4441 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4443 pic16_emitpLabel( label3->key );
4444 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4445 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4449 pic16_emitpLabel(label2->key);
4450 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4451 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4452 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4454 /* result is in wreg */
4455 if(AOP_TYPE(result) != AOP_ACC)
4456 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4458 pic16_popReleaseTempReg( pct3, 1);
4459 pic16_popReleaseTempReg( pct2, 1);
4460 pic16_popReleaseTempReg( pct1, 1);
4465 /* signed is a little bit more difficult */
4467 /* save the signs of the operands */
4468 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4470 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4471 pic16_emitcode("push","acc"); /* save it on the stack */
4473 /* now sign adjust for both left & right */
4474 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4476 lbl = newiTempLabel(NULL);
4477 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4478 pic16_emitcode("cpl","a");
4479 pic16_emitcode("inc","a");
4480 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4481 pic16_emitcode("mov","b,a");
4483 /* sign adjust left side */
4484 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4487 lbl = newiTempLabel(NULL);
4488 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4489 pic16_emitcode("cpl","a");
4490 pic16_emitcode("inc","a");
4491 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4493 /* now the division */
4494 pic16_emitcode("div","ab");
4495 /* we are interested in the lower order
4497 pic16_emitcode("mov","b,a");
4498 lbl = newiTempLabel(NULL);
4499 pic16_emitcode("pop","acc");
4500 /* if there was an over flow we don't
4501 adjust the sign of the result */
4502 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4503 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4505 pic16_emitcode("clr","a");
4506 pic16_emitcode("subb","a,b");
4507 pic16_emitcode("mov","b,a");
4508 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4510 /* now we are done */
4511 pic16_aopPut(AOP(result),"b",0);
4513 pic16_emitcode("mov","c,b.7");
4514 pic16_emitcode("subb","a,acc");
4517 pic16_aopPut(AOP(result),"a",offset++);
4521 /*-----------------------------------------------------------------*/
4522 /* genDiv - generates code for division */
4523 /*-----------------------------------------------------------------*/
4524 static void genDiv (iCode *ic)
4526 operand *left = IC_LEFT(ic);
4527 operand *right = IC_RIGHT(ic);
4528 operand *result= IC_RESULT(ic);
4531 /* Division is a very lengthy algorithm, so it is better
4532 * to call support routines than inlining algorithm.
4533 * Division functions written here just in case someone
4534 * wants to inline and not use the support libraries -- VR */
4538 /* assign the amsops */
4539 pic16_aopOp (left,ic,FALSE);
4540 pic16_aopOp (right,ic,FALSE);
4541 pic16_aopOp (result,ic,TRUE);
4543 /* special cases first */
4545 if (AOP_TYPE(left) == AOP_CRY &&
4546 AOP_TYPE(right)== AOP_CRY) {
4547 genDivbits(left,right,result);
4551 /* if both are of size == 1 */
4552 if (AOP_SIZE(left) == 1 &&
4553 AOP_SIZE(right) == 1 ) {
4554 genDivOneByte(left,right,result);
4558 /* should have been converted to function call */
4561 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4562 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4563 pic16_freeAsmop(result,NULL,ic,TRUE);
4566 /*-----------------------------------------------------------------*/
4567 /* genModbits :- modulus of bits */
4568 /*-----------------------------------------------------------------*/
4569 static void genModbits (operand *left,
4577 werror(W_POSSBUG2, __FILE__, __LINE__);
4578 /* the result must be bit */
4579 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4580 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4584 pic16_emitcode("div","ab");
4585 pic16_emitcode("mov","a,b");
4586 pic16_emitcode("rrc","a");
4587 pic16_aopPut(AOP(result),"c",0);
4590 /*-----------------------------------------------------------------*/
4591 /* genModOneByte : 8 bit modulus */
4592 /*-----------------------------------------------------------------*/
4593 static void genModOneByte (operand *left,
4597 sym_link *opetype = operandType(result);
4602 werror(W_POSSBUG2, __FILE__, __LINE__);
4604 /* signed or unsigned */
4605 if (SPEC_USIGN(opetype)) {
4606 /* unsigned is easy */
4607 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4608 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4610 pic16_emitcode("div","ab");
4611 pic16_aopPut(AOP(result),"b",0);
4615 /* signed is a little bit more difficult */
4617 /* save the signs of the operands */
4618 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4621 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4622 pic16_emitcode("push","acc"); /* save it on the stack */
4624 /* now sign adjust for both left & right */
4625 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4628 lbl = newiTempLabel(NULL);
4629 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4630 pic16_emitcode("cpl","a");
4631 pic16_emitcode("inc","a");
4632 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4633 pic16_emitcode("mov","b,a");
4635 /* sign adjust left side */
4636 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4639 lbl = newiTempLabel(NULL);
4640 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4641 pic16_emitcode("cpl","a");
4642 pic16_emitcode("inc","a");
4643 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4645 /* now the multiplication */
4646 pic16_emitcode("div","ab");
4647 /* we are interested in the lower order
4649 lbl = newiTempLabel(NULL);
4650 pic16_emitcode("pop","acc");
4651 /* if there was an over flow we don't
4652 adjust the sign of the result */
4653 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4654 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4656 pic16_emitcode("clr","a");
4657 pic16_emitcode("subb","a,b");
4658 pic16_emitcode("mov","b,a");
4659 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4661 /* now we are done */
4662 pic16_aopPut(AOP(result),"b",0);
4666 /*-----------------------------------------------------------------*/
4667 /* genMod - generates code for division */
4668 /*-----------------------------------------------------------------*/
4669 static void genMod (iCode *ic)
4671 operand *left = IC_LEFT(ic);
4672 operand *right = IC_RIGHT(ic);
4673 operand *result= IC_RESULT(ic);
4677 /* assign the amsops */
4678 pic16_aopOp (left,ic,FALSE);
4679 pic16_aopOp (right,ic,FALSE);
4680 pic16_aopOp (result,ic,TRUE);
4682 /* special cases first */
4684 if (AOP_TYPE(left) == AOP_CRY &&
4685 AOP_TYPE(right)== AOP_CRY) {
4686 genModbits(left,right,result);
4690 /* if both are of size == 1 */
4691 if (AOP_SIZE(left) == 1 &&
4692 AOP_SIZE(right) == 1 ) {
4693 genModOneByte(left,right,result);
4697 /* should have been converted to function call */
4701 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4702 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4703 pic16_freeAsmop(result,NULL,ic,TRUE);
4706 /*-----------------------------------------------------------------*/
4707 /* genIfxJump :- will create a jump depending on the ifx */
4708 /*-----------------------------------------------------------------*/
4710 note: May need to add parameter to indicate when a variable is in bit space.
4712 static void genIfxJump (iCode *ic, char *jval)
4716 /* if true label then we jump if condition
4718 if ( IC_TRUE(ic) ) {
4720 if(strcmp(jval,"a") == 0)
4722 else if (strcmp(jval,"c") == 0)
4725 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4726 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4729 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4730 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4734 /* false label is present */
4735 if(strcmp(jval,"a") == 0)
4737 else if (strcmp(jval,"c") == 0)
4740 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4741 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4744 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4745 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4750 /* mark the icode as generated */
4754 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4758 /* if true label then we jump if condition
4760 if ( IC_TRUE(ic) ) {
4761 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4762 pic16_emitpcode(POC_BTFSC, jop);
4764 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4765 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4768 /* false label is present */
4769 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4770 pic16_emitpcode(POC_BTFSS, jop);
4772 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4773 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4777 /* mark the icode as generated */
4784 /*-----------------------------------------------------------------*/
4786 /*-----------------------------------------------------------------*/
4787 static void genSkip(iCode *ifx,int status_bit)
4789 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4793 if ( IC_TRUE(ifx) ) {
4794 switch(status_bit) {
4809 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4810 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4814 switch(status_bit) {
4828 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4829 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4836 /*-----------------------------------------------------------------*/
4838 /*-----------------------------------------------------------------*/
4839 static void genSkipc(resolvedIfx *rifx)
4841 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4851 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4852 rifx->generated = 1;
4855 #if !(USE_SIMPLE_GENCMP)
4856 /*-----------------------------------------------------------------*/
4858 /*-----------------------------------------------------------------*/
4859 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4861 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4866 if( (rifx->condition ^ invert_condition) & 1)
4871 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4872 rifx->generated = 1;
4877 /*-----------------------------------------------------------------*/
4879 /*-----------------------------------------------------------------*/
4880 static void genSkipz(iCode *ifx, int condition)
4891 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4893 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4896 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4898 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4903 #if !(USE_SIMPLE_GENCMP)
4904 /*-----------------------------------------------------------------*/
4906 /*-----------------------------------------------------------------*/
4907 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4913 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4915 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4918 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4919 rifx->generated = 1;
4924 /*-----------------------------------------------------------------*/
4925 /* genChkZeroes :- greater or less than comparison */
4926 /* For each byte in a literal that is zero, inclusive or the */
4927 /* the corresponding byte in the operand with W */
4928 /* returns true if any of the bytes are zero */
4929 /*-----------------------------------------------------------------*/
4930 static int genChkZeroes(operand *op, int lit, int size)
4937 i = (lit >> (size*8)) & 0xff;
4941 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4943 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4953 /*-----------------------------------------------------------------*/
4954 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4955 /* aop (if it's NOT a literal) or from lit (if */
4956 /* aop is a literal) */
4957 /*-----------------------------------------------------------------*/
4958 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4959 if (aop->type == AOP_LIT) {
4960 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4962 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4966 /*-----------------------------------------------------------------*/
4967 /* genCmp :- greater or less than comparison */
4968 /*-----------------------------------------------------------------*/
4970 #if USE_SIMPLE_GENCMP /* { */
4972 /* genCmp performs a left < right comparison, stores
4973 * the outcome in result (if != NULL) and generates
4974 * control flow code for the ifx (if != NULL).
4976 * This version leaves in sequences like
4977 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4978 * which should be optmized by the peephole
4979 * optimizer - RN 2005-01-01 */
4980 static void genCmp (operand *left,operand *right,
4981 operand *result, iCode *ifx, int sign)
4994 assert (AOP_SIZE(left) == AOP_SIZE(right));
4995 assert (left && right);
4997 size = AOP_SIZE(right) - 1;
4998 mask = (0x100UL << (size*8)) - 1;
4999 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5004 resolveIfx (&rIfx, ifx);
5006 /* handle for special cases */
5007 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5010 /**********************************************************************
5011 * handle bits - bit compares are promoted to int compares seemingly! *
5012 **********************************************************************/
5014 // THIS IS COMPLETELY UNTESTED!
5015 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5016 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5017 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5018 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5021 // 1 < {0,1} is false --> clear C by skipping the next instruction
5022 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5023 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5024 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5025 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5026 emitCLRC; // only skipped for left=0 && right=1
5028 goto correct_result_in_carry;
5032 /*************************************************
5033 * make sure that left is register (or the like) *
5034 *************************************************/
5035 if (!isAOP_REGlike(left)) {
5036 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5037 assert (isAOP_LIT(left));
5038 assert (isAOP_REGlike(right));
5039 // swap left and right
5040 // left < right <==> right > left <==> (right >= left + 1)
5041 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5043 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5044 // MAXVALUE < right? always false
5045 if (performedLt) emitCLRC; else emitSETC;
5046 goto correct_result_in_carry;
5049 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5050 // that's why we handled it above.
5057 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1"
5058 } else if (isAOP_LIT(right)) {
5059 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5062 assert (isAOP_REGlike(left)); // left must be register or the like
5063 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5065 /*************************************************
5066 * special cases go here *
5067 *************************************************/
5069 if (isAOP_LIT(right)) {
5071 // unsigned comparison to a literal
5072 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5074 // unsigned left < 0? always false
5075 if (performedLt) emitCLRC; else emitSETC;
5076 goto correct_result_in_carry;
5079 // signed comparison to a literal
5080 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5081 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5082 // signed left < 0x80000000? always false
5083 if (performedLt) emitCLRC; else emitSETC;
5084 goto correct_result_in_carry;
5085 } else if (lit == 0) {
5086 // compare left < 0; set CARRY if SIGNBIT(left) is set
5087 if (performedLt) emitSETC; else emitCLRC;
5088 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5089 if (performedLt) emitCLRC; else emitSETC;
5090 goto correct_result_in_carry;
5093 } // right is literal
5095 /*************************************************
5096 * perform a general case comparison *
5097 * make sure we get CARRY==1 <==> left >= right *
5098 *************************************************/
5099 // compare most significant bytes
5100 //DEBUGpc ("comparing bytes at offset %d", size);
5102 // unsigned comparison
5103 mov2w_regOrLit (AOP(right), lit, size);
5104 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5106 // signed comparison
5107 // (add 2^n to both operands then perform an unsigned comparison)
5108 if (isAOP_LIT(right)) {
5109 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5110 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5112 if (litbyte == 0x80) {
5113 // left >= 0x80 -- always true, but more bytes to come
5114 pic16_mov2w (AOP(left), size);
5115 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5118 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5119 pic16_mov2w (AOP(left), size);
5120 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5121 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5124 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5125 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5126 pic16_mov2w (AOP(left), size);
5127 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5128 pic16_emitpcode (POC_MOVWF, pctemp);
5129 pic16_mov2w (AOP(right), size);
5130 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5131 pic16_emitpcode (POC_SUBFW, pctemp);
5132 //pic16_popReleaseTempReg(pctemp, 1);
5136 // compare remaining bytes (treat as unsigned case from above)
5137 templbl = newiTempLabel ( NULL );
5140 //DEBUGpc ("comparing bytes at offset %d", offs);
5141 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5142 mov2w_regOrLit (AOP(right), lit, offs);
5143 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5145 pic16_emitpLabel (templbl->key);
5146 goto result_in_carry;
5150 /****************************************************
5151 * now CARRY contains the result of the comparison: *
5152 * SUBWF sets CARRY iff *
5153 * F-W >= 0 <==> F >= W <==> !(F < W) *
5154 * (F=left, W=right) *
5155 ****************************************************/
5158 if (result && AOP_TYPE(result) != AOP_CRY) {
5159 // value will be stored
5162 // value wil only be used in the following genSkipc()
5163 rIfx.condition ^= 1;
5167 correct_result_in_carry:
5169 // assign result to variable (if neccessary)
5170 if (result && AOP_TYPE(result) != AOP_CRY) {
5171 //DEBUGpc ("assign result");
5172 size = AOP_SIZE(result);
5174 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5176 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5179 // perform conditional jump
5181 //DEBUGpc ("generate control flow");
5190 static void genCmp (operand *left,operand *right,
5191 operand *result, iCode *ifx, int sign)
5193 int size; //, offset = 0 ;
5194 unsigned long lit = 0L,i = 0;
5195 resolvedIfx rFalseIfx;
5196 // resolvedIfx rTrueIfx;
5198 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5201 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5202 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5208 resolveIfx(&rFalseIfx,ifx);
5209 truelbl = newiTempLabel(NULL);
5210 size = max(AOP_SIZE(left),AOP_SIZE(right));
5212 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5216 /* if literal is on the right then swap with left */
5217 if ((AOP_TYPE(right) == AOP_LIT)) {
5218 operand *tmp = right ;
5219 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5220 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5223 lit = (lit - 1) & mask;
5226 rFalseIfx.condition ^= 1;
5229 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5230 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5234 //if(IC_TRUE(ifx) == NULL)
5235 /* if left & right are bit variables */
5236 if (AOP_TYPE(left) == AOP_CRY &&
5237 AOP_TYPE(right) == AOP_CRY ) {
5238 assert (0 && "bit variables used in genCmp");
5239 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5240 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5242 /* subtract right from left if at the
5243 end the carry flag is set then we know that
5244 left is greater than right */
5246 symbol *lbl = newiTempLabel(NULL);
5249 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5250 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5254 if(AOP_TYPE(right) == AOP_LIT) {
5256 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5258 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5265 genSkipCond(&rFalseIfx,left,size-1,7);
5267 /* no need to compare to 0...*/
5268 /* NOTE: this is a de-generate compare that most certainly
5269 * creates some dead code. */
5270 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5272 if(ifx) ifx->generated = 1;
5279 //i = (lit >> (size*8)) & 0xff;
5280 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5282 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5284 i = ((0-lit) & 0xff);
5287 /* lit is 0x7f, all signed chars are less than
5288 * this except for 0x7f itself */
5289 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5290 genSkipz2(&rFalseIfx,0);
5292 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5293 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5294 genSkipc(&rFalseIfx);
5299 genSkipz2(&rFalseIfx,1);
5301 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5302 genSkipc(&rFalseIfx);
5306 if(ifx) ifx->generated = 1;
5310 /* chars are out of the way. now do ints and longs */
5313 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5320 genSkipCond(&rFalseIfx,left,size,7);
5321 if(ifx) ifx->generated = 1;
5326 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5328 //rFalseIfx.condition ^= 1;
5329 //genSkipCond(&rFalseIfx,left,size,7);
5330 //rFalseIfx.condition ^= 1;
5332 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5333 if(rFalseIfx.condition)
5334 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5336 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5338 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5339 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5340 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5343 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5345 if(rFalseIfx.condition) {
5347 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5353 genSkipc(&rFalseIfx);
5354 pic16_emitpLabel(truelbl->key);
5355 if(ifx) ifx->generated = 1;
5362 if( (lit & 0xff) == 0) {
5363 /* lower byte is zero */
5364 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5365 i = ((lit >> 8) & 0xff) ^0x80;
5366 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5367 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5368 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5369 genSkipc(&rFalseIfx);
5372 if(ifx) ifx->generated = 1;
5377 /* Special cases for signed longs */
5378 if( (lit & 0xffffff) == 0) {
5379 /* lower byte is zero */
5380 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5381 i = ((lit >> 8*3) & 0xff) ^0x80;
5382 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5383 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5384 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5385 genSkipc(&rFalseIfx);
5388 if(ifx) ifx->generated = 1;
5396 if(lit & (0x80 << (size*8))) {
5397 /* lit is negative */
5398 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5400 //genSkipCond(&rFalseIfx,left,size,7);
5402 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5404 if(rFalseIfx.condition)
5405 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5407 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5411 /* lit is positive */
5412 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5413 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5414 if(rFalseIfx.condition)
5415 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5417 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5422 This works, but is only good for ints.
5423 It also requires a "known zero" register.
5424 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5425 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5426 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5427 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5428 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5429 genSkipc(&rFalseIfx);
5431 pic16_emitpLabel(truelbl->key);
5432 if(ifx) ifx->generated = 1;
5436 /* There are no more special cases, so perform a general compare */
5438 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5439 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5443 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5445 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5447 //rFalseIfx.condition ^= 1;
5448 genSkipc(&rFalseIfx);
5450 pic16_emitpLabel(truelbl->key);
5452 if(ifx) ifx->generated = 1;
5459 /* sign is out of the way. So now do an unsigned compare */
5460 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5463 /* General case - compare to an unsigned literal on the right.*/
5465 i = (lit >> (size*8)) & 0xff;
5466 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5467 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5469 i = (lit >> (size*8)) & 0xff;
5472 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5474 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5476 /* this byte of the lit is zero,
5477 *if it's not the last then OR in the variable */
5479 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5484 pic16_emitpLabel(lbl->key);
5485 // pic16_emitpLabel(truelbl->key);
5486 //if(emitFinalCheck)
5487 genSkipc(&rFalseIfx);
5489 pic16_emitpLabel(truelbl->key);
5491 if(ifx) ifx->generated = 1;
5498 if(AOP_TYPE(left) == AOP_LIT) {
5499 //symbol *lbl = newiTempLabel(NULL);
5501 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5504 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5507 if((lit == 0) && (sign == 0)){
5510 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5512 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5514 genSkipz2(&rFalseIfx,0);
5515 if(ifx) ifx->generated = 1;
5522 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5523 /* degenerate compare can never be true */
5524 if(rFalseIfx.condition == 0)
5525 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5527 if(ifx) ifx->generated = 1;
5532 /* signed comparisons to a literal byte */
5534 int lp1 = (lit+1) & 0xff;
5536 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5539 rFalseIfx.condition ^= 1;
5540 genSkipCond(&rFalseIfx,right,0,7);
5543 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5544 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5545 genSkipz2(&rFalseIfx,1);
5548 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5549 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5550 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5551 rFalseIfx.condition ^= 1;
5552 genSkipc(&rFalseIfx);
5556 /* unsigned comparisons to a literal byte */
5558 switch(lit & 0xff ) {
5560 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5561 genSkipz2(&rFalseIfx,0);
5564 rFalseIfx.condition ^= 1;
5565 genSkipCond(&rFalseIfx,right,0,7);
5569 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5570 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5571 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5572 rFalseIfx.condition ^= 1;
5573 if (AOP_TYPE(result) == AOP_CRY)
5574 genSkipc(&rFalseIfx);
5576 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5577 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5583 if(ifx) ifx->generated = 1;
5584 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5590 /* Size is greater than 1 */
5598 /* this means lit = 0xffffffff, or -1 */
5601 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5602 rFalseIfx.condition ^= 1;
5603 genSkipCond(&rFalseIfx,right,size,7);
5604 if(ifx) ifx->generated = 1;
5606 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5615 if(rFalseIfx.condition) {
5616 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5617 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5620 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5622 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5626 if(rFalseIfx.condition) {
5627 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5628 pic16_emitpLabel(truelbl->key);
5630 rFalseIfx.condition ^= 1;
5631 genSkipCond(&rFalseIfx,right,s,7);
5634 if(ifx) ifx->generated = 1;
5636 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5642 if((size == 1) && (0 == (lp1&0xff))) {
5643 /* lower byte of signed word is zero */
5644 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5645 i = ((lp1 >> 8) & 0xff) ^0x80;
5646 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5647 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5648 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5650 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5652 if(ifx) ifx->generated = 1;
5655 rFalseIfx.condition ^= 1;
5656 genSkipc(&rFalseIfx);
5657 if(ifx) ifx->generated = 1;
5663 if(lit & (0x80 << (size*8))) {
5664 /* Lit is less than zero */
5665 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5666 //rFalseIfx.condition ^= 1;
5667 //genSkipCond(&rFalseIfx,left,size,7);
5668 //rFalseIfx.condition ^= 1;
5669 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5670 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5672 if(rFalseIfx.condition)
5673 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5675 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5679 /* Lit is greater than or equal to zero */
5680 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5681 //rFalseIfx.condition ^= 1;
5682 //genSkipCond(&rFalseIfx,right,size,7);
5683 //rFalseIfx.condition ^= 1;
5685 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5686 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5688 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5689 if(rFalseIfx.condition)
5690 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5692 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5696 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5697 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5701 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5703 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5705 rFalseIfx.condition ^= 1;
5706 //rFalseIfx.condition = 1;
5707 genSkipc(&rFalseIfx);
5709 pic16_emitpLabel(truelbl->key);
5711 if(ifx) ifx->generated = 1;
5714 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5721 /* compare word or long to an unsigned literal on the right.*/
5726 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5729 break; /* handled above */
5732 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5734 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5735 genSkipz2(&rFalseIfx,0);
5739 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5741 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5744 if(rFalseIfx.condition)
5745 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5747 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5750 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5751 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5753 rFalseIfx.condition ^= 1;
5754 genSkipc(&rFalseIfx);
5757 pic16_emitpLabel(truelbl->key);
5759 if(ifx) ifx->generated = 1;
5761 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5769 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5770 i = (lit >> (size*8)) & 0xff;
5772 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5773 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5776 i = (lit >> (size*8)) & 0xff;
5779 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5781 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5783 /* this byte of the lit is zero,
5784 * if it's not the last then OR in the variable */
5786 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5791 pic16_emitpLabel(lbl->key);
5793 rFalseIfx.condition ^= 1;
5795 genSkipc(&rFalseIfx);
5799 pic16_emitpLabel(truelbl->key);
5800 if(ifx) ifx->generated = 1;
5802 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5808 /* Compare two variables */
5810 DEBUGpic16_emitcode(";sign","%d",sign);
5814 /* Sigh. thus sucks... */
5818 pctemp = pic16_popGetTempReg(1);
5819 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5820 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5821 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5822 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5823 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5824 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5825 pic16_popReleaseTempReg(pctemp, 1);
5827 /* Signed char comparison */
5828 /* Special thanks to Nikolai Golovchenko for this snippet */
5829 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5830 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5831 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5832 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5833 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5834 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5836 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5837 genSkipc(&rFalseIfx);
5839 if(ifx) ifx->generated = 1;
5841 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5849 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5850 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5854 /* The rest of the bytes of a multi-byte compare */
5858 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5861 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5862 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5867 pic16_emitpLabel(lbl->key);
5869 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5870 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5871 (AOP_TYPE(result) == AOP_REG)) {
5872 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5873 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5875 genSkipc(&rFalseIfx);
5877 //genSkipc(&rFalseIfx);
5878 if(ifx) ifx->generated = 1;
5881 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5889 if ((AOP_TYPE(result) != AOP_CRY)
5890 && AOP_SIZE(result)) {
5891 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5893 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5895 pic16_outBitC(result);
5897 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5898 /* if the result is used in the next
5899 ifx conditional branch then generate
5900 code a little differently */
5902 genIfxJump (ifx,"c");
5904 pic16_outBitC(result);
5905 /* leave the result in acc */
5910 #elif 0 /* VR version of genCmp() */ /* } else { */
5912 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5913 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5914 operand *result, int offset, int invert_op)
5918 /* check condition, > or < ?? */
5919 if(rIfx->condition != 0)invert_op ^= 1;
5921 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5923 if(!ifx)invert_op ^= 1;
5925 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5926 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5929 if(!invert_op)return POC_CPFSGT;
5930 else return POC_CPFSLT;
5933 static int compareAopfirstpass=1;
5935 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5936 operand *oper, int offset, operand *result,
5937 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5943 /* invert if there is a result to be loaded, in order to fit,
5944 * SETC/CLRC sequence */
5945 if(AOP_SIZE(result))invert_op ^= 1;
5947 // if(sign && !offset)invert_op ^= 1;
5949 // if(sign)invert_op ^= 1;
5951 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5953 if(AOP_SIZE(result) && compareAopfirstpass) {
5956 pic16_emitpcode(POC_SETF, pcop2);
5961 pic16_emitpcode(POC_CLRF, pcop2);
5967 compareAopfirstpass = 0;
5969 /* there is a bug when comparing operands with size > 1,
5970 * because higher bytes can be equal and test should be performed
5971 * to the next lower byte, current algorithm, considers operands
5972 * inequal in these cases! -- VR 20041107 */
5976 pic16_emitpcode(op, pcop);
5978 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5981 if((!sign || !offset) && AOP_SIZE(result)) {
5984 pic16_emitpcode(POC_CLRF, pcop2);
5989 pic16_emitpcode(POC_SETF, pcop2);
5994 /* don't emit final branch (offset == 0) */
5998 pic16_emitpcode(POC_RRCF, pcop2);
6000 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6003 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6004 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6005 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6007 truelbl = newiTempLabel( NULL );
6008 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6009 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6010 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6012 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6013 pic16_emitpLabel(truelbl->key);
6015 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6020 static void genCmp (operand *left, operand *right,
6021 operand *result, iCode *ifx, int sign)
6025 resolvedIfx rFalseIfx;
6026 symbol *falselbl, *tlbl;
6030 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6032 resolveIfx(&rFalseIfx, ifx);
6033 size = max(AOP_SIZE(left), AOP_SIZE(right));
6035 /* if left & right are bit variables */
6036 if(AOP_TYPE(left) == AOP_CRY
6037 && AOP_TYPE(right) == AOP_CRY ) {
6039 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6040 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6042 werror(W_POSSBUG2, __FILE__, __LINE__);
6046 /* if literal is on the right then swap with left */
6047 if((AOP_TYPE(right) == AOP_LIT)) {
6048 operand *tmp = right ;
6049 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6051 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6053 // lit = (lit - 1) & mask;
6056 rFalseIfx.condition ^= 1; /* reverse compare */
6058 if ((AOP_TYPE(left) == AOP_LIT)) {
6059 /* float compares are handled by support functions */
6060 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6063 /* actual comparing algorithm */
6064 // size = AOP_SIZE( right );
6066 falselbl = newiTempLabel( NULL );
6067 if(AOP_TYPE(left) == AOP_LIT) {
6068 /* compare to literal */
6069 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6072 pCodeOp *pct, *pct2;
6075 /* signed compare */
6076 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6078 pct = pic16_popCopyReg(&pic16_pc_prodl);
6079 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6080 tlbl = newiTempLabel( NULL );
6082 /* first compare signs:
6083 * a. if both are positive, compare just like unsigned
6084 * b. if both are negative, invert cmpop, compare just like unsigned
6085 * c. if different signs, determine the result directly */
6091 tlbl1 = newiTempLabel( NULL );
6092 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6096 /* literal is zero or positive:
6097 * a. if carry is zero, too, continue compare,
6098 * b. if carry is set, then continue depending on cmpop ^ condition:
6099 * 1. '<' return false (literal < variable),
6100 * 2. '>' return true (literal > variable) */
6101 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6102 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6105 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6106 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6110 /* literal is negative:
6111 * a. if carry is set, too, continue compare,
6112 * b. if carry is zero, then continue depending on cmpop ^ condition:
6113 * 1. '<' return true (literal < variable),
6114 * 2. '>' return false (literal > variable) */
6115 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6116 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6118 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6119 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6124 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6126 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6127 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6132 pic16_emitpLabel( tlbl1->key );
6135 compareAopfirstpass=1;
6136 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6137 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6138 // pic16_emitpcode(POC_MOVWF, pct);
6140 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6141 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6142 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6143 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6147 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6148 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6149 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6150 // pic16_emitpcode(POC_MOVWF, pct);
6152 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6153 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6154 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6155 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6156 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6160 if(ifx)ifx->generated = 1;
6162 if(AOP_SIZE(result)) {
6163 pic16_emitpLabel(tlbl->key);
6164 pic16_emitpLabel(falselbl->key);
6165 pic16_outBitOp( result, pct2 );
6167 pic16_emitpLabel(tlbl->key);
6171 /* unsigned compare */
6172 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6174 compareAopfirstpass=1;
6177 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6178 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6181 if(ifx)ifx->generated = 1;
6183 if(AOP_SIZE(result)) {
6184 pic16_emitpLabel(falselbl->key);
6185 pic16_outBitC( result );
6190 /* compare registers */
6191 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6195 pCodeOp *pct, *pct2;
6197 /* signed compare */
6198 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6200 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6201 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6202 tlbl = newiTempLabel( NULL );
6204 compareAopfirstpass=1;
6207 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6208 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6209 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6210 pic16_emitpcode(POC_MOVWF, pct);
6212 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6213 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6214 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6216 /* WREG already holds left + 0x80 */
6217 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6220 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6221 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6222 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6223 pic16_emitpcode(POC_MOVWF, pct);
6225 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6226 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6227 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6229 /* WREG already holds left + 0x80 */
6230 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6231 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6234 if(ifx)ifx->generated = 1;
6236 if(AOP_SIZE(result)) {
6237 pic16_emitpLabel(tlbl->key);
6238 pic16_emitpLabel(falselbl->key);
6239 pic16_outBitOp( result, pct2 );
6241 pic16_emitpLabel(tlbl->key);
6245 /* unsigned compare */
6246 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6248 compareAopfirstpass=1;
6251 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6252 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6256 if(ifx)ifx->generated = 1;
6257 if(AOP_SIZE(result)) {
6259 pic16_emitpLabel(falselbl->key);
6260 pic16_outBitC( result );
6271 /*-----------------------------------------------------------------*/
6272 /* genCmpGt :- greater than comparison */
6273 /*-----------------------------------------------------------------*/
6274 static void genCmpGt (iCode *ic, iCode *ifx)
6276 operand *left, *right, *result;
6277 sym_link *letype , *retype;
6283 right= IC_RIGHT(ic);
6284 result = IC_RESULT(ic);
6286 letype = getSpec(operandType(left));
6287 retype =getSpec(operandType(right));
6288 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6289 /* assign the amsops */
6290 pic16_aopOp (left,ic,FALSE);
6291 pic16_aopOp (right,ic,FALSE);
6292 pic16_aopOp (result,ic,TRUE);
6294 genCmp(right, left, result, ifx, sign);
6296 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6297 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6298 pic16_freeAsmop(result,NULL,ic,TRUE);
6301 /*-----------------------------------------------------------------*/
6302 /* genCmpLt - less than comparisons */
6303 /*-----------------------------------------------------------------*/
6304 static void genCmpLt (iCode *ic, iCode *ifx)
6306 operand *left, *right, *result;
6307 sym_link *letype , *retype;
6313 right= IC_RIGHT(ic);
6314 result = IC_RESULT(ic);
6316 letype = getSpec(operandType(left));
6317 retype =getSpec(operandType(right));
6318 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6320 /* assign the amsops */
6321 pic16_aopOp (left,ic,FALSE);
6322 pic16_aopOp (right,ic,FALSE);
6323 pic16_aopOp (result,ic,TRUE);
6325 genCmp(left, right, result, ifx, sign);
6327 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6328 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6329 pic16_freeAsmop(result,NULL,ic,TRUE);
6334 // FIXME reenable literal optimisation when the pic16 port is stable
6336 /*-----------------------------------------------------------------*/
6337 /* genc16bit2lit - compare a 16 bit value to a literal */
6338 /*-----------------------------------------------------------------*/
6339 static void genc16bit2lit(operand *op, int lit, int offset)
6343 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6344 if( (lit&0xff) == 0)
6349 switch( BYTEofLONG(lit,i)) {
6351 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6354 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6357 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6360 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6361 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6366 switch( BYTEofLONG(lit,i)) {
6368 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6372 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6376 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6379 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6381 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6390 /*-----------------------------------------------------------------*/
6391 /* gencjneshort - compare and jump if not equal */
6392 /*-----------------------------------------------------------------*/
6393 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6395 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6397 int res_offset = 0; /* the result may be a different size then left or right */
6398 int res_size = AOP_SIZE(result);
6400 symbol *lbl, *lbl_done;
6402 unsigned long lit = 0L;
6403 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6405 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6406 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6408 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6409 resolveIfx(&rIfx,ifx);
6410 lbl = newiTempLabel(NULL);
6411 lbl_done = newiTempLabel(NULL);
6414 /* if the left side is a literal or
6415 if the right is in a pointer register and left
6417 if ((AOP_TYPE(left) == AOP_LIT) ||
6418 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6423 if(AOP_TYPE(right) == AOP_LIT)
6424 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6426 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6427 preserve_result = 1;
6429 if(result && !preserve_result)
6432 for(i = 0; i < AOP_SIZE(result); i++)
6433 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6437 /* if the right side is a literal then anything goes */
6438 if (AOP_TYPE(right) == AOP_LIT &&
6439 AOP_TYPE(left) != AOP_DIR ) {
6442 genc16bit2lit(left, lit, 0);
6444 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6447 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6450 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6451 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6453 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6457 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6459 if(res_offset < res_size-1)
6467 /* if the right side is in a register or in direct space or
6468 if the left is a pointer register & right is not */
6469 else if (AOP_TYPE(right) == AOP_REG ||
6470 AOP_TYPE(right) == AOP_DIR ||
6471 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6472 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6473 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6474 int lbl_key = lbl->key;
6477 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6478 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6480 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6481 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6482 __FUNCTION__,__LINE__);
6486 /* switch(size) { */
6488 /* genc16bit2lit(left, lit, 0); */
6490 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6495 if((AOP_TYPE(left) == AOP_DIR) &&
6496 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6498 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6499 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6501 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6503 switch (lit & 0xff) {
6505 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6508 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6509 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6510 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6514 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6515 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6516 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6517 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6521 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6522 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6527 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6530 if(AOP_TYPE(result) == AOP_CRY) {
6531 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6536 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6538 /* fix me. probably need to check result size too */
6539 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6544 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6545 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6552 if(res_offset < res_size-1)
6557 } else if(AOP_TYPE(right) == AOP_REG &&
6558 AOP_TYPE(left) != AOP_DIR){
6561 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6562 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6563 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6568 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6570 if(res_offset < res_size-1)
6575 /* right is a pointer reg need both a & b */
6577 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6579 pic16_emitcode("mov","b,%s",l);
6580 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6581 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6586 if(result && preserve_result)
6589 for(i = 0; i < AOP_SIZE(result); i++)
6590 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6593 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6595 if(result && preserve_result)
6596 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6599 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6601 pic16_emitpLabel(lbl->key);
6603 if(result && preserve_result)
6606 for(i = 0; i < AOP_SIZE(result); i++)
6607 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6609 pic16_emitpLabel(lbl_done->key);
6612 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6620 /*-----------------------------------------------------------------*/
6621 /* gencjne - compare and jump if not equal */
6622 /*-----------------------------------------------------------------*/
6623 static void gencjne(operand *left, operand *right, iCode *ifx)
6625 symbol *tlbl = newiTempLabel(NULL);
6627 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6628 gencjneshort(left, right, lbl);
6630 pic16_emitcode("mov","a,%s",one);
6631 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6632 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6633 pic16_emitcode("clr","a");
6634 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6636 pic16_emitpLabel(lbl->key);
6637 pic16_emitpLabel(tlbl->key);
6643 /*-----------------------------------------------------------------*/
6644 /* is_LitOp - check if operand has to be treated as literal */
6645 /*-----------------------------------------------------------------*/
6646 static bool is_LitOp(operand *op)
6648 return ((AOP_TYPE(op) == AOP_LIT)
6649 || ( (AOP_TYPE(op) == AOP_PCODE)
6650 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6651 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6654 /*-----------------------------------------------------------------*/
6655 /* is_LitAOp - check if operand has to be treated as literal */
6656 /*-----------------------------------------------------------------*/
6657 static bool is_LitAOp(asmop *aop)
6659 return ((aop->type == AOP_LIT)
6660 || ( (aop->type == AOP_PCODE)
6661 && ( (aop->aopu.pcop->type == PO_LITERAL)
6662 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6667 /*-----------------------------------------------------------------*/
6668 /* genCmpEq - generates code for equal to */
6669 /*-----------------------------------------------------------------*/
6670 static void genCmpEq (iCode *ic, iCode *ifx)
6672 operand *left, *right, *result;
6673 symbol *falselbl = newiTempLabel(NULL);
6674 symbol *donelbl = newiTempLabel(NULL);
6676 int preserve_result = 0;
6677 int generate_result = 0;
6679 unsigned long lit = -1;
6683 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6684 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6685 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6687 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6689 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6691 werror(W_POSSBUG2, __FILE__, __LINE__);
6692 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6693 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6697 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6699 operand *tmp = right ;
6704 if (AOP_TYPE(right) == AOP_LIT) {
6705 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6708 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6709 preserve_result = 1;
6711 if(result && AOP_SIZE(result))
6712 generate_result = 1;
6714 if(generate_result && !preserve_result)
6716 for(i = 0; i < AOP_SIZE(result); i++)
6717 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6720 for(i=0; i < AOP_SIZE(left); i++)
6722 if(AOP_TYPE(left) != AOP_ACC)
6725 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6727 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6729 if(is_LitOp(right)) {
6730 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6731 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6734 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6736 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6741 if(generate_result && preserve_result)
6743 for(i = 0; i < AOP_SIZE(result); i++)
6744 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6748 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6750 if(generate_result && preserve_result)
6751 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6753 if(ifx && IC_TRUE(ifx))
6754 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6756 if(ifx && IC_FALSE(ifx))
6757 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6759 pic16_emitpLabel(falselbl->key);
6763 if(ifx && IC_FALSE(ifx))
6764 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6766 if(generate_result && preserve_result)
6768 for(i = 0; i < AOP_SIZE(result); i++)
6769 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6772 pic16_emitpLabel(donelbl->key);
6778 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6779 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6780 pic16_freeAsmop(result,NULL,ic,TRUE);
6786 // old version kept for reference
6788 /*-----------------------------------------------------------------*/
6789 /* genCmpEq - generates code for equal to */
6790 /*-----------------------------------------------------------------*/
6791 static void genCmpEq (iCode *ic, iCode *ifx)
6793 operand *left, *right, *result;
6794 unsigned long lit = 0L;
6796 symbol *falselbl = newiTempLabel(NULL);
6799 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6802 DEBUGpic16_emitcode ("; ifx is non-null","");
6804 DEBUGpic16_emitcode ("; ifx is null","");
6806 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6807 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6808 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6810 size = max(AOP_SIZE(left),AOP_SIZE(right));
6812 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6814 /* if literal, literal on the right or
6815 if the right is in a pointer register and left
6817 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6818 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6819 operand *tmp = right ;
6825 if(ifx && !AOP_SIZE(result)){
6827 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6828 /* if they are both bit variables */
6829 if (AOP_TYPE(left) == AOP_CRY &&
6830 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6831 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6832 if(AOP_TYPE(right) == AOP_LIT){
6833 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6835 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6836 pic16_emitcode("cpl","c");
6837 } else if(lit == 1L) {
6838 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6840 pic16_emitcode("clr","c");
6842 /* AOP_TYPE(right) == AOP_CRY */
6844 symbol *lbl = newiTempLabel(NULL);
6845 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6846 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6847 pic16_emitcode("cpl","c");
6848 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6850 /* if true label then we jump if condition
6852 tlbl = newiTempLabel(NULL);
6853 if ( IC_TRUE(ifx) ) {
6854 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6855 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6857 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6858 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6860 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6863 /* left and right are both bit variables, result is carry */
6866 resolveIfx(&rIfx,ifx);
6868 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6869 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6870 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6871 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6876 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6878 /* They're not both bit variables. Is the right a literal? */
6879 if(AOP_TYPE(right) == AOP_LIT) {
6880 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6885 switch(lit & 0xff) {
6887 if ( IC_TRUE(ifx) ) {
6888 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6890 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6892 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6893 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6897 if ( IC_TRUE(ifx) ) {
6898 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6900 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6902 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6903 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6907 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6909 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6914 /* end of size == 1 */
6918 genc16bit2lit(left,lit,offset);
6921 /* end of size == 2 */
6926 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6927 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6928 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6929 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6932 /* search for patterns that can be optimized */
6934 genc16bit2lit(left,lit,0);
6938 emitSKPZ; // if hi word unequal
6940 emitSKPNZ; // if hi word equal
6942 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6943 genc16bit2lit(left,lit,2);
6946 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6947 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6951 pic16_emitpLabel(falselbl->key);
6960 } else if(AOP_TYPE(right) == AOP_CRY ) {
6961 /* we know the left is not a bit, but that the right is */
6962 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6963 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6964 pic16_popGet(AOP(right),offset));
6965 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6967 /* if the two are equal, then W will be 0 and the Z bit is set
6968 * we could test Z now, or go ahead and check the high order bytes if
6969 * the variable we're comparing is larger than a byte. */
6972 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6974 if ( IC_TRUE(ifx) ) {
6976 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6977 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6980 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6981 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6985 /* They're both variables that are larger than bits */
6988 tlbl = newiTempLabel(NULL);
6991 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6992 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6994 if ( IC_TRUE(ifx) ) {
6998 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7000 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7001 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7005 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7008 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7009 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7014 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7016 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7017 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7021 if(s>1 && IC_TRUE(ifx)) {
7022 pic16_emitpLabel(tlbl->key);
7023 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7027 /* mark the icode as generated */
7032 /* if they are both bit variables */
7033 if (AOP_TYPE(left) == AOP_CRY &&
7034 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7035 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7036 if(AOP_TYPE(right) == AOP_LIT){
7037 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7039 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7040 pic16_emitcode("cpl","c");
7041 } else if(lit == 1L) {
7042 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7044 pic16_emitcode("clr","c");
7046 /* AOP_TYPE(right) == AOP_CRY */
7048 symbol *lbl = newiTempLabel(NULL);
7049 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7050 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7051 pic16_emitcode("cpl","c");
7052 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7055 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7056 pic16_outBitC(result);
7060 genIfxJump (ifx,"c");
7063 /* if the result is used in an arithmetic operation
7064 then put the result in place */
7065 pic16_outBitC(result);
7068 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7069 gencjne(left,right,result,ifx);
7072 gencjne(left,right,newiTempLabel(NULL));
7074 if(IC_TRUE(ifx)->key)
7075 gencjne(left,right,IC_TRUE(ifx)->key);
7077 gencjne(left,right,IC_FALSE(ifx)->key);
7081 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7082 pic16_aopPut(AOP(result),"a",0);
7087 genIfxJump (ifx,"a");
7091 /* if the result is used in an arithmetic operation
7092 then put the result in place */
7094 if (AOP_TYPE(result) != AOP_CRY)
7095 pic16_outAcc(result);
7097 /* leave the result in acc */
7101 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7102 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7103 pic16_freeAsmop(result,NULL,ic,TRUE);
7107 /*-----------------------------------------------------------------*/
7108 /* ifxForOp - returns the icode containing the ifx for operand */
7109 /*-----------------------------------------------------------------*/
7110 static iCode *ifxForOp ( operand *op, iCode *ic )
7114 /* if true symbol then needs to be assigned */
7115 if (IS_TRUE_SYMOP(op))
7118 /* if this has register type condition and
7119 the next instruction is ifx with the same operand
7120 and live to of the operand is upto the ifx only then */
7122 && ic->next->op == IFX
7123 && IC_COND(ic->next)->key == op->key
7124 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7126 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7132 ic->next->op == IFX &&
7133 IC_COND(ic->next)->key == op->key) {
7134 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7139 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7141 ic->next->op == IFX)
7142 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7145 ic->next->op == IFX &&
7146 IC_COND(ic->next)->key == op->key) {
7147 DEBUGpic16_emitcode ("; "," key is okay");
7148 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7149 OP_SYMBOL(op)->liveTo,
7154 /* the code below is completely untested
7155 * it just allows ulong2fs.c compile -- VR */
7158 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7159 __FILE__, __FUNCTION__, __LINE__);
7161 /* if this has register type condition and
7162 the next instruction is ifx with the same operand
7163 and live to of the operand is upto the ifx only then */
7165 ic->next->op == IFX &&
7166 IC_COND(ic->next)->key == op->key &&
7167 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7171 ic->next->op == IFX &&
7172 IC_COND(ic->next)->key == op->key) {
7173 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7177 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7178 __FILE__, __FUNCTION__, __LINE__);
7180 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7185 /*-----------------------------------------------------------------*/
7186 /* genAndOp - for && operation */
7187 /*-----------------------------------------------------------------*/
7188 static void genAndOp (iCode *ic)
7190 operand *left,*right, *result;
7195 /* note here that && operations that are in an
7196 if statement are taken away by backPatchLabels
7197 only those used in arthmetic operations remain */
7198 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7199 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7200 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7202 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7204 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7205 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7206 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7208 /* if both are bit variables */
7209 /* if (AOP_TYPE(left) == AOP_CRY && */
7210 /* AOP_TYPE(right) == AOP_CRY ) { */
7211 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7212 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7213 /* pic16_outBitC(result); */
7215 /* tlbl = newiTempLabel(NULL); */
7216 /* pic16_toBoolean(left); */
7217 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7218 /* pic16_toBoolean(right); */
7219 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7220 /* pic16_outBitAcc(result); */
7223 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7224 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7225 pic16_freeAsmop(result,NULL,ic,TRUE);
7229 /*-----------------------------------------------------------------*/
7230 /* genOrOp - for || operation */
7231 /*-----------------------------------------------------------------*/
7234 modified this code, but it doesn't appear to ever get called
7237 static void genOrOp (iCode *ic)
7239 operand *left,*right, *result;
7244 /* note here that || operations that are in an
7245 if statement are taken away by backPatchLabels
7246 only those used in arthmetic operations remain */
7247 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7248 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7249 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7251 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7253 /* if both are bit variables */
7254 if (AOP_TYPE(left) == AOP_CRY &&
7255 AOP_TYPE(right) == AOP_CRY ) {
7256 pic16_emitcode("clrc","");
7257 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7258 AOP(left)->aopu.aop_dir,
7259 AOP(left)->aopu.aop_dir);
7260 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7261 AOP(right)->aopu.aop_dir,
7262 AOP(right)->aopu.aop_dir);
7263 pic16_emitcode("setc","");
7266 tlbl = newiTempLabel(NULL);
7267 pic16_toBoolean(left);
7269 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7270 pic16_toBoolean(right);
7271 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7273 pic16_outBitAcc(result);
7276 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7277 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7278 pic16_freeAsmop(result,NULL,ic,TRUE);
7281 /*-----------------------------------------------------------------*/
7282 /* isLiteralBit - test if lit == 2^n */
7283 /*-----------------------------------------------------------------*/
7284 static int isLiteralBit(unsigned long lit)
7286 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7287 0x100L,0x200L,0x400L,0x800L,
7288 0x1000L,0x2000L,0x4000L,0x8000L,
7289 0x10000L,0x20000L,0x40000L,0x80000L,
7290 0x100000L,0x200000L,0x400000L,0x800000L,
7291 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7292 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7295 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7296 for(idx = 0; idx < 32; idx++)
7302 /*-----------------------------------------------------------------*/
7303 /* continueIfTrue - */
7304 /*-----------------------------------------------------------------*/
7305 static void continueIfTrue (iCode *ic)
7309 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7313 /*-----------------------------------------------------------------*/
7315 /*-----------------------------------------------------------------*/
7316 static void jumpIfTrue (iCode *ic)
7320 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7324 /*-----------------------------------------------------------------*/
7325 /* jmpTrueOrFalse - */
7326 /*-----------------------------------------------------------------*/
7327 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7329 // ugly but optimized by peephole
7332 symbol *nlbl = newiTempLabel(NULL);
7333 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7334 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7335 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7336 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7338 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7339 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7344 /*-----------------------------------------------------------------*/
7345 /* genAnd - code for and */
7346 /*-----------------------------------------------------------------*/
7347 static void genAnd (iCode *ic, iCode *ifx)
7349 operand *left, *right, *result;
7351 unsigned long lit = 0L;
7357 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7358 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7359 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7361 resolveIfx(&rIfx,ifx);
7363 /* if left is a literal & right is not then exchange them */
7364 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7365 AOP_NEEDSACC(left)) {
7366 operand *tmp = right ;
7371 /* if result = right then exchange them */
7372 if(pic16_sameRegs(AOP(result),AOP(right))){
7373 operand *tmp = right ;
7378 /* if right is bit then exchange them */
7379 if (AOP_TYPE(right) == AOP_CRY &&
7380 AOP_TYPE(left) != AOP_CRY){
7381 operand *tmp = right ;
7385 if(AOP_TYPE(right) == AOP_LIT)
7386 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7388 size = AOP_SIZE(result);
7390 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7393 // result = bit & yy;
7394 if (AOP_TYPE(left) == AOP_CRY){
7395 // c = bit & literal;
7396 if(AOP_TYPE(right) == AOP_LIT){
7398 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7401 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7404 if(size && (AOP_TYPE(result) == AOP_CRY)){
7405 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7408 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7412 pic16_emitcode("clr","c");
7415 if (AOP_TYPE(right) == AOP_CRY){
7417 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7418 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7421 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7423 pic16_emitcode("rrc","a");
7424 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7430 pic16_outBitC(result);
7432 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7433 genIfxJump(ifx, "c");
7437 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7438 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7439 if((AOP_TYPE(right) == AOP_LIT) &&
7440 (AOP_TYPE(result) == AOP_CRY) &&
7441 (AOP_TYPE(left) != AOP_CRY)){
7442 int posbit = isLiteralBit(lit);
7446 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7449 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7455 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7456 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7458 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7459 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7462 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7463 size = AOP_SIZE(left);
7466 int bp = posbit, ofs=0;
7473 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7474 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7478 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7479 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7481 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7488 symbol *tlbl = newiTempLabel(NULL);
7489 int sizel = AOP_SIZE(left);
7495 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7497 /* patch provided by Aaron Colwell */
7498 if((posbit = isLiteralBit(bytelit)) != 0) {
7499 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7500 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7501 (posbit-1),0, PO_GPR_REGISTER));
7503 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7504 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7506 if (bytelit == 0xff) {
7507 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7508 * a peephole could optimize it out -- VR */
7509 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7511 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7512 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7515 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7516 pic16_popGetLabel(tlbl->key));
7520 /* old code, left here for reference -- VR 09/2004 */
7521 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7523 if((posbit = isLiteralBit(bytelit)) != 0)
7524 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7526 if(bytelit != 0x0FFL)
7527 pic16_emitcode("anl","a,%s",
7528 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7529 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7535 // bit = left & literal
7538 pic16_emitpLabel(tlbl->key);
7540 // if(left & literal)
7543 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7546 pic16_emitpLabel(tlbl->key);
7551 pic16_outBitC(result);
7555 /* if left is same as result */
7556 if(pic16_sameRegs(AOP(result),AOP(left))){
7558 for(;size--; offset++,lit>>=8) {
7559 if(AOP_TYPE(right) == AOP_LIT){
7560 switch(lit & 0xff) {
7562 /* and'ing with 0 has clears the result */
7563 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7564 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7567 /* and'ing with 0xff is a nop when the result and left are the same */
7572 int p = pic16_my_powof2( (~lit) & 0xff );
7574 /* only one bit is set in the literal, so use a bcf instruction */
7575 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7576 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7579 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7580 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7581 if(know_W != (lit&0xff))
7582 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7584 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7589 if (AOP_TYPE(left) == AOP_ACC) {
7590 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7592 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7593 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7600 // left & result in different registers
7601 if(AOP_TYPE(result) == AOP_CRY){
7603 // if(size), result in bit
7604 // if(!size && ifx), conditional oper: if(left & right)
7605 symbol *tlbl = newiTempLabel(NULL);
7606 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7608 pic16_emitcode("setb","c");
7610 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7611 pic16_emitcode("anl","a,%s",
7612 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7613 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7618 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7619 pic16_outBitC(result);
7621 jmpTrueOrFalse(ifx, tlbl);
7623 for(;(size--);offset++) {
7625 // result = left & right
7626 if(AOP_TYPE(right) == AOP_LIT){
7627 int t = (lit >> (offset*8)) & 0x0FFL;
7630 pic16_emitcode("clrf","%s",
7631 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7632 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7635 pic16_emitcode("movf","%s,w",
7636 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7637 pic16_emitcode("movwf","%s",
7638 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7639 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7640 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7643 pic16_emitcode("movlw","0x%x",t);
7644 pic16_emitcode("andwf","%s,w",
7645 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7646 pic16_emitcode("movwf","%s",
7647 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7649 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7650 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7651 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7656 if (AOP_TYPE(left) == AOP_ACC) {
7657 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7658 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7660 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7661 pic16_emitcode("andwf","%s,w",
7662 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7663 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7664 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7666 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7667 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7673 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7674 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7675 pic16_freeAsmop(result,NULL,ic,TRUE);
7678 /*-----------------------------------------------------------------*/
7679 /* genOr - code for or */
7680 /*-----------------------------------------------------------------*/
7681 static void genOr (iCode *ic, iCode *ifx)
7683 operand *left, *right, *result;
7685 unsigned long lit = 0L;
7687 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7689 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7690 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7691 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7693 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7695 /* if left is a literal & right is not then exchange them */
7696 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7697 AOP_NEEDSACC(left)) {
7698 operand *tmp = right ;
7703 /* if result = right then exchange them */
7704 if(pic16_sameRegs(AOP(result),AOP(right))){
7705 operand *tmp = right ;
7710 /* if right is bit then exchange them */
7711 if (AOP_TYPE(right) == AOP_CRY &&
7712 AOP_TYPE(left) != AOP_CRY){
7713 operand *tmp = right ;
7718 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7720 if(AOP_TYPE(right) == AOP_LIT)
7721 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7723 size = AOP_SIZE(result);
7727 if (AOP_TYPE(left) == AOP_CRY){
7728 if(AOP_TYPE(right) == AOP_LIT){
7729 // c = bit & literal;
7731 // lit != 0 => result = 1
7732 if(AOP_TYPE(result) == AOP_CRY){
7734 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7735 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7736 // AOP(result)->aopu.aop_dir,
7737 // AOP(result)->aopu.aop_dir);
7739 continueIfTrue(ifx);
7743 // lit == 0 => result = left
7744 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7746 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7749 if (AOP_TYPE(right) == AOP_CRY){
7750 if(pic16_sameRegs(AOP(result),AOP(left))){
7752 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7753 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7754 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7756 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7757 AOP(result)->aopu.aop_dir,
7758 AOP(result)->aopu.aop_dir);
7759 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7760 AOP(right)->aopu.aop_dir,
7761 AOP(right)->aopu.aop_dir);
7762 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7763 AOP(result)->aopu.aop_dir,
7764 AOP(result)->aopu.aop_dir);
7766 if( AOP_TYPE(result) == AOP_ACC) {
7767 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7768 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7769 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7770 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7774 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7775 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7776 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7777 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7779 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7780 AOP(result)->aopu.aop_dir,
7781 AOP(result)->aopu.aop_dir);
7782 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7783 AOP(right)->aopu.aop_dir,
7784 AOP(right)->aopu.aop_dir);
7785 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7786 AOP(left)->aopu.aop_dir,
7787 AOP(left)->aopu.aop_dir);
7788 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7789 AOP(result)->aopu.aop_dir,
7790 AOP(result)->aopu.aop_dir);
7795 symbol *tlbl = newiTempLabel(NULL);
7796 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7799 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7800 if( AOP_TYPE(right) == AOP_ACC) {
7801 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7803 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7804 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7809 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7810 pic16_emitcode(";XXX setb","c");
7811 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7812 AOP(left)->aopu.aop_dir,tlbl->key+100);
7813 pic16_toBoolean(right);
7814 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7815 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7816 jmpTrueOrFalse(ifx, tlbl);
7820 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7827 pic16_outBitC(result);
7829 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7830 genIfxJump(ifx, "c");
7834 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7835 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7836 if((AOP_TYPE(right) == AOP_LIT) &&
7837 (AOP_TYPE(result) == AOP_CRY) &&
7838 (AOP_TYPE(left) != AOP_CRY)){
7840 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7843 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7845 continueIfTrue(ifx);
7848 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7849 // lit = 0, result = boolean(left)
7851 pic16_emitcode(";XXX setb","c");
7852 pic16_toBoolean(right);
7854 symbol *tlbl = newiTempLabel(NULL);
7855 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7857 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7859 genIfxJump (ifx,"a");
7863 pic16_outBitC(result);
7867 /* if left is same as result */
7868 if(pic16_sameRegs(AOP(result),AOP(left))){
7870 for(;size--; offset++,lit>>=8) {
7871 if(AOP_TYPE(right) == AOP_LIT){
7872 if((lit & 0xff) == 0)
7873 /* or'ing with 0 has no effect */
7876 int p = pic16_my_powof2(lit & 0xff);
7878 /* only one bit is set in the literal, so use a bsf instruction */
7879 pic16_emitpcode(POC_BSF,
7880 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7882 if(know_W != (lit & 0xff))
7883 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7884 know_W = lit & 0xff;
7885 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7890 if (AOP_TYPE(left) == AOP_ACC) {
7891 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7892 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7894 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7895 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7897 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7898 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7904 // left & result in different registers
7905 if(AOP_TYPE(result) == AOP_CRY){
7907 // if(size), result in bit
7908 // if(!size && ifx), conditional oper: if(left | right)
7909 symbol *tlbl = newiTempLabel(NULL);
7910 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7911 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7915 pic16_emitcode(";XXX setb","c");
7917 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7918 pic16_emitcode(";XXX orl","a,%s",
7919 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7920 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7925 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7926 pic16_outBitC(result);
7928 jmpTrueOrFalse(ifx, tlbl);
7929 } else for(;(size--);offset++){
7931 // result = left & right
7932 if(AOP_TYPE(right) == AOP_LIT){
7933 int t = (lit >> (offset*8)) & 0x0FFL;
7936 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7937 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7939 pic16_emitcode("movf","%s,w",
7940 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7941 pic16_emitcode("movwf","%s",
7942 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7945 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7946 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7947 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7949 pic16_emitcode("movlw","0x%x",t);
7950 pic16_emitcode("iorwf","%s,w",
7951 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7952 pic16_emitcode("movwf","%s",
7953 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7959 // faster than result <- left, anl result,right
7960 // and better if result is SFR
7961 if (AOP_TYPE(left) == AOP_ACC) {
7962 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7963 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7965 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7966 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7968 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7969 pic16_emitcode("iorwf","%s,w",
7970 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7972 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7973 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7978 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7979 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7980 pic16_freeAsmop(result,NULL,ic,TRUE);
7983 /*-----------------------------------------------------------------*/
7984 /* genXor - code for xclusive or */
7985 /*-----------------------------------------------------------------*/
7986 static void genXor (iCode *ic, iCode *ifx)
7988 operand *left, *right, *result;
7990 unsigned long lit = 0L;
7992 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7994 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7995 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7996 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7998 /* if left is a literal & right is not ||
7999 if left needs acc & right does not */
8000 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8001 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8002 operand *tmp = right ;
8007 /* if result = right then exchange them */
8008 if(pic16_sameRegs(AOP(result),AOP(right))){
8009 operand *tmp = right ;
8014 /* if right is bit then exchange them */
8015 if (AOP_TYPE(right) == AOP_CRY &&
8016 AOP_TYPE(left) != AOP_CRY){
8017 operand *tmp = right ;
8021 if(AOP_TYPE(right) == AOP_LIT)
8022 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8024 size = AOP_SIZE(result);
8028 if (AOP_TYPE(left) == AOP_CRY){
8029 if(AOP_TYPE(right) == AOP_LIT){
8030 // c = bit & literal;
8032 // lit>>1 != 0 => result = 1
8033 if(AOP_TYPE(result) == AOP_CRY){
8035 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8036 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8038 continueIfTrue(ifx);
8041 pic16_emitcode("setb","c");
8045 // lit == 0, result = left
8046 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8048 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8050 // lit == 1, result = not(left)
8051 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8052 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8053 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8054 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8057 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8058 pic16_emitcode("cpl","c");
8065 symbol *tlbl = newiTempLabel(NULL);
8066 if (AOP_TYPE(right) == AOP_CRY){
8068 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8071 int sizer = AOP_SIZE(right);
8073 // if val>>1 != 0, result = 1
8074 pic16_emitcode("setb","c");
8076 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8078 // test the msb of the lsb
8079 pic16_emitcode("anl","a,#0xfe");
8080 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8084 pic16_emitcode("rrc","a");
8086 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8087 pic16_emitcode("cpl","c");
8088 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8093 pic16_outBitC(result);
8095 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8096 genIfxJump(ifx, "c");
8100 if(pic16_sameRegs(AOP(result),AOP(left))){
8101 /* if left is same as result */
8102 for(;size--; offset++) {
8103 if(AOP_TYPE(right) == AOP_LIT){
8104 int t = (lit >> (offset*8)) & 0x0FFL;
8108 if (IS_AOP_PREG(left)) {
8109 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8110 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8111 pic16_aopPut(AOP(result),"a",offset);
8113 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8114 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8115 pic16_emitcode("xrl","%s,%s",
8116 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8117 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8120 if (AOP_TYPE(left) == AOP_ACC)
8121 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8123 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8124 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8126 if (IS_AOP_PREG(left)) {
8127 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8128 pic16_aopPut(AOP(result),"a",offset);
8130 pic16_emitcode("xrl","%s,a",
8131 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8137 // left & result in different registers
8138 if(AOP_TYPE(result) == AOP_CRY){
8140 // if(size), result in bit
8141 // if(!size && ifx), conditional oper: if(left ^ right)
8142 symbol *tlbl = newiTempLabel(NULL);
8143 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8145 pic16_emitcode("setb","c");
8147 if((AOP_TYPE(right) == AOP_LIT) &&
8148 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8149 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8151 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8152 pic16_emitcode("xrl","a,%s",
8153 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8155 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8160 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8161 pic16_outBitC(result);
8163 jmpTrueOrFalse(ifx, tlbl);
8164 } else for(;(size--);offset++){
8166 // result = left & right
8167 if(AOP_TYPE(right) == AOP_LIT){
8168 int t = (lit >> (offset*8)) & 0x0FFL;
8171 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8172 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8173 pic16_emitcode("movf","%s,w",
8174 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8175 pic16_emitcode("movwf","%s",
8176 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8179 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8180 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8181 pic16_emitcode("comf","%s,w",
8182 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8183 pic16_emitcode("movwf","%s",
8184 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8187 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8188 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8189 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8190 pic16_emitcode("movlw","0x%x",t);
8191 pic16_emitcode("xorwf","%s,w",
8192 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8193 pic16_emitcode("movwf","%s",
8194 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8200 // faster than result <- left, anl result,right
8201 // and better if result is SFR
8202 if (AOP_TYPE(left) == AOP_ACC) {
8203 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8204 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8206 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8207 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8208 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8209 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8211 if ( AOP_TYPE(result) != AOP_ACC){
8212 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8213 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8219 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8220 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8221 pic16_freeAsmop(result,NULL,ic,TRUE);
8224 /*-----------------------------------------------------------------*/
8225 /* genInline - write the inline code out */
8226 /*-----------------------------------------------------------------*/
8227 static void genInline (iCode *ic)
8229 char *buffer, *bp, *bp1;
8231 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8233 _G.inLine += (!options.asmpeep);
8235 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8236 strcpy(buffer,IC_INLINE(ic));
8238 while((bp1=strstr(bp, "\\n"))) {
8246 /* This is an experimental code for #pragma inline
8247 and is temporarily disabled for 2.5.0 release */
8255 cbuf = Safe_strdup(buffer);
8256 cblen = strlen(buffer)+1;
8257 memset(cbuf, 0, cblen);
8262 if(*bp != '%')*bp1++ = *bp++;
8268 if(i>elementsInSet(asmInlineMap))break;
8271 s = indexSet(asmInlineMap, i);
8272 DEBUGpc("searching symbol s = `%s'", s);
8273 sym = findSym(SymbolTab, NULL, s);
8276 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8278 strcat(bp1, sym->rname);
8284 if(strlen(bp1) > cblen - 16) {
8285 int i = strlen(cbuf);
8287 cbuf = realloc(cbuf, cblen);
8288 memset(cbuf+i, 0, 50);
8294 buffer = Safe_strdup( cbuf );
8301 /* emit each line as a code */
8307 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8315 /* print label, use this special format with NULL directive
8316 * to denote that the argument should not be indented with tab */
8317 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8324 if ((bp1 != bp) && *bp1)
8325 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8330 _G.inLine -= (!options.asmpeep);
8333 /*-----------------------------------------------------------------*/
8334 /* genRRC - rotate right with carry */
8335 /*-----------------------------------------------------------------*/
8336 static void genRRC (iCode *ic)
8338 operand *left , *result ;
8339 int size, offset = 0, same;
8341 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8343 /* rotate right with carry */
8345 result=IC_RESULT(ic);
8346 pic16_aopOp (left,ic,FALSE);
8347 pic16_aopOp (result,ic,TRUE);
8349 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8351 same = pic16_sameRegs(AOP(result),AOP(left));
8353 size = AOP_SIZE(result);
8355 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8357 /* get the lsb and put it into the carry */
8358 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8365 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8367 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8368 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8374 pic16_freeAsmop(left,NULL,ic,TRUE);
8375 pic16_freeAsmop(result,NULL,ic,TRUE);
8378 /*-----------------------------------------------------------------*/
8379 /* genRLC - generate code for rotate left with carry */
8380 /*-----------------------------------------------------------------*/
8381 static void genRLC (iCode *ic)
8383 operand *left , *result ;
8384 int size, offset = 0;
8387 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8388 /* rotate right with carry */
8390 result=IC_RESULT(ic);
8391 pic16_aopOp (left,ic,FALSE);
8392 pic16_aopOp (result,ic,TRUE);
8394 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8396 same = pic16_sameRegs(AOP(result),AOP(left));
8398 /* move it to the result */
8399 size = AOP_SIZE(result);
8401 /* get the msb and put it into the carry */
8402 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8409 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8411 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8412 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8419 pic16_freeAsmop(left,NULL,ic,TRUE);
8420 pic16_freeAsmop(result,NULL,ic,TRUE);
8424 /* gpasm can get the highest order bit with HIGH/UPPER
8425 * so the following probably is not needed -- VR */
8427 /*-----------------------------------------------------------------*/
8428 /* genGetHbit - generates code get highest order bit */
8429 /*-----------------------------------------------------------------*/
8430 static void genGetHbit (iCode *ic)
8432 operand *left, *result;
8434 result=IC_RESULT(ic);
8435 pic16_aopOp (left,ic,FALSE);
8436 pic16_aopOp (result,ic,FALSE);
8438 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8439 /* get the highest order byte into a */
8440 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8441 if(AOP_TYPE(result) == AOP_CRY){
8442 pic16_emitcode("rlc","a");
8443 pic16_outBitC(result);
8446 pic16_emitcode("rl","a");
8447 pic16_emitcode("anl","a,#0x01");
8448 pic16_outAcc(result);
8452 pic16_freeAsmop(left,NULL,ic,TRUE);
8453 pic16_freeAsmop(result,NULL,ic,TRUE);
8457 /*-----------------------------------------------------------------*/
8458 /* AccRol - rotate left accumulator by known count */
8459 /*-----------------------------------------------------------------*/
8460 static void AccRol (int shCount)
8462 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8463 shCount &= 0x0007; // shCount : 0..7
8468 pic16_emitcode("rl","a");
8471 pic16_emitcode("rl","a");
8472 pic16_emitcode("rl","a");
8475 pic16_emitcode("swap","a");
8476 pic16_emitcode("rr","a");
8479 pic16_emitcode("swap","a");
8482 pic16_emitcode("swap","a");
8483 pic16_emitcode("rl","a");
8486 pic16_emitcode("rr","a");
8487 pic16_emitcode("rr","a");
8490 pic16_emitcode("rr","a");
8496 /*-----------------------------------------------------------------*/
8497 /* AccLsh - left shift accumulator by known count */
8498 /*-----------------------------------------------------------------*/
8499 static void AccLsh (int shCount)
8501 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8507 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8510 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8511 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8514 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8515 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8518 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8521 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8522 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8525 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8526 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8529 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8533 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8536 /*-----------------------------------------------------------------*/
8537 /* AccRsh - right shift accumulator by known count */
8538 /*-----------------------------------------------------------------*/
8539 static void AccRsh (int shCount, int andmask)
8541 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8546 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8549 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8550 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8553 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8554 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8557 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8560 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8561 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8564 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8565 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8568 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8573 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8575 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8579 /*-----------------------------------------------------------------*/
8580 /* AccSRsh - signed right shift accumulator by known count */
8581 /*-----------------------------------------------------------------*/
8582 static void AccSRsh (int shCount)
8585 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8588 pic16_emitcode("mov","c,acc.7");
8589 pic16_emitcode("rrc","a");
8590 } else if(shCount == 2){
8591 pic16_emitcode("mov","c,acc.7");
8592 pic16_emitcode("rrc","a");
8593 pic16_emitcode("mov","c,acc.7");
8594 pic16_emitcode("rrc","a");
8596 tlbl = newiTempLabel(NULL);
8597 /* rotate right accumulator */
8598 AccRol(8 - shCount);
8599 /* and kill the higher order bits */
8600 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8601 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8602 pic16_emitcode("orl","a,#0x%02x",
8603 (unsigned char)~SRMask[shCount]);
8604 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8610 /*-----------------------------------------------------------------*/
8611 /* shiftR1Left2Result - shift right one byte from left to result */
8612 /*-----------------------------------------------------------------*/
8613 static void shiftR1Left2ResultSigned (operand *left, int offl,
8614 operand *result, int offr,
8619 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8621 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8625 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8627 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8629 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8630 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8636 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8638 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8640 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8641 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8643 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8644 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8650 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8652 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8653 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8656 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8657 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8658 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8660 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8661 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8663 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8667 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8668 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8669 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8670 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8671 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8675 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8677 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8678 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8680 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8681 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8682 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8683 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8684 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8689 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8690 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8691 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8692 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8693 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8694 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8696 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8697 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8698 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8699 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8700 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8706 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8707 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8708 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8709 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8711 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8712 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8713 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8721 /*-----------------------------------------------------------------*/
8722 /* shiftR1Left2Result - shift right one byte from left to result */
8723 /*-----------------------------------------------------------------*/
8724 static void shiftR1Left2Result (operand *left, int offl,
8725 operand *result, int offr,
8726 int shCount, int sign)
8730 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8732 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8734 /* Copy the msb into the carry if signed. */
8736 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8746 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8748 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8749 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8755 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8757 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8758 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8761 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8766 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8768 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8769 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8772 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8773 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8774 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8775 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8779 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8780 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8781 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8785 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8786 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8787 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8789 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8794 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8795 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8796 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8797 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8798 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8803 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8804 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8805 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8814 /*-----------------------------------------------------------------*/
8815 /* shiftL1Left2Result - shift left one byte from left to result */
8816 /*-----------------------------------------------------------------*/
8817 static void shiftL1Left2Result (operand *left, int offl,
8818 operand *result, int offr, int shCount)
8823 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8825 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8826 DEBUGpic16_emitcode ("; ***","same = %d",same);
8827 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8829 /* shift left accumulator */
8830 //AccLsh(shCount); // don't comment out just yet...
8831 // pic16_aopPut(AOP(result),"a",offr);
8835 /* Shift left 1 bit position */
8836 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8838 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8840 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8841 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8845 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8846 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8847 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8848 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8851 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8852 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8853 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8854 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8855 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8858 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8859 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8860 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8863 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8864 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8865 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8866 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8869 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8870 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8871 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8872 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8873 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8876 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8877 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8878 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8882 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8887 /*-----------------------------------------------------------------*/
8888 /* movLeft2Result - move byte from left to result */
8889 /*-----------------------------------------------------------------*/
8890 static void movLeft2Result (operand *left, int offl,
8891 operand *result, int offr)
8894 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8895 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8896 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8898 if (*l == '@' && (IS_AOP_PREG(result))) {
8899 pic16_emitcode("mov","a,%s",l);
8900 pic16_aopPut(AOP(result),"a",offr);
8902 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8903 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8908 /*-----------------------------------------------------------------*/
8909 /* shiftL2Left2Result - shift left two bytes from left to result */
8910 /*-----------------------------------------------------------------*/
8911 static void shiftL2Left2Result (operand *left, int offl,
8912 operand *result, int offr, int shCount)
8914 int same = pic16_sameRegs(AOP(result), AOP(left));
8917 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8919 if (same && (offl != offr)) { // shift bytes
8922 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8923 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8925 } else { // just treat as different later on
8938 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8939 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8940 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8944 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8945 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8951 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8952 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8953 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8954 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8955 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8956 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8957 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8959 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8960 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8964 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8965 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8966 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8967 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8968 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8969 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8970 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8971 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8972 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8973 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8976 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8977 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8978 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8979 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8980 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8990 /* note, use a mov/add for the shift since the mov has a
8991 chance of getting optimized out */
8992 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8993 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8994 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8995 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8996 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9000 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9001 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9007 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9008 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9009 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9010 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9011 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9012 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9013 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9014 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9018 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9019 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9023 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9024 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9025 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9026 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9028 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9029 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9030 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9031 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9032 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9033 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9034 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9035 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9038 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9039 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9040 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9041 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9042 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9047 /*-----------------------------------------------------------------*/
9048 /* shiftR2Left2Result - shift right two bytes from left to result */
9049 /*-----------------------------------------------------------------*/
9050 static void shiftR2Left2Result (operand *left, int offl,
9051 operand *result, int offr,
9052 int shCount, int sign)
9054 int same = pic16_sameRegs(AOP(result), AOP(left));
9056 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9058 if (same && (offl != offr)) { // shift right bytes
9061 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9062 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9064 } else { // just treat as different later on
9076 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9081 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9082 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9084 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9085 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9086 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9087 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9092 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9095 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9096 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9103 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9104 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9105 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9107 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9108 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9109 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9110 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9112 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9113 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9114 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9116 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9117 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9118 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9119 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9120 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9124 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9125 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9129 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9130 pic16_emitpcode(POC_BTFSC,
9131 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9132 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9140 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9141 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9143 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9144 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9145 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9146 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9148 pic16_emitpcode(POC_BTFSC,
9149 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9150 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9152 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9153 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9154 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9155 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9157 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9158 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9159 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9160 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9161 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9162 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9163 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9164 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9166 pic16_emitpcode(POC_BTFSC,
9167 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9168 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9170 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9171 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9178 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9179 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9180 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9181 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9184 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9186 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9191 /*-----------------------------------------------------------------*/
9192 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9193 /*-----------------------------------------------------------------*/
9194 static void shiftLLeftOrResult (operand *left, int offl,
9195 operand *result, int offr, int shCount)
9197 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9199 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9200 /* shift left accumulator */
9202 /* or with result */
9203 /* back to result */
9204 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9207 /*-----------------------------------------------------------------*/
9208 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9209 /*-----------------------------------------------------------------*/
9210 static void shiftRLeftOrResult (operand *left, int offl,
9211 operand *result, int offr, int shCount)
9213 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9215 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9216 /* shift right accumulator */
9218 /* or with result */
9219 /* back to result */
9220 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9223 /*-----------------------------------------------------------------*/
9224 /* genlshOne - left shift a one byte quantity by known count */
9225 /*-----------------------------------------------------------------*/
9226 static void genlshOne (operand *result, operand *left, int shCount)
9228 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9229 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9232 /*-----------------------------------------------------------------*/
9233 /* genlshTwo - left shift two bytes by known amount != 0 */
9234 /*-----------------------------------------------------------------*/
9235 static void genlshTwo (operand *result,operand *left, int shCount)
9239 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9240 size = pic16_getDataSize(result);
9242 /* if shCount >= 8 */
9248 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9250 movLeft2Result(left, LSB, result, MSB16);
9252 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9255 /* 1 <= shCount <= 7 */
9258 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9260 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9264 /*-----------------------------------------------------------------*/
9265 /* shiftLLong - shift left one long from left to result */
9266 /* offr = LSB or MSB16 */
9267 /*-----------------------------------------------------------------*/
9268 static void shiftLLong (operand *left, operand *result, int offr )
9270 int size = AOP_SIZE(result);
9271 int same = pic16_sameRegs(AOP(left),AOP(result));
9274 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9276 if (same && (offr == MSB16)) { //shift one byte
9277 for(i=size-1;i>=MSB16;i--) {
9278 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9279 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9282 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9285 if (size > LSB+offr ){
9287 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9289 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9290 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9294 if(size > MSB16+offr){
9296 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9298 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9299 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9303 if(size > MSB24+offr){
9305 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9307 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9308 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9312 if(size > MSB32+offr){
9314 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9316 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9317 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9321 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9325 /*-----------------------------------------------------------------*/
9326 /* genlshFour - shift four byte by a known amount != 0 */
9327 /*-----------------------------------------------------------------*/
9328 static void genlshFour (operand *result, operand *left, int shCount)
9332 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9333 size = AOP_SIZE(result);
9335 /* if shifting more that 3 bytes */
9336 if (shCount >= 24 ) {
9339 /* lowest order of left goes to the highest
9340 order of the destination */
9341 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9343 movLeft2Result(left, LSB, result, MSB32);
9345 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9346 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9347 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9352 /* more than two bytes */
9353 else if ( shCount >= 16 ) {
9354 /* lower order two bytes goes to higher order two bytes */
9356 /* if some more remaining */
9358 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9360 movLeft2Result(left, MSB16, result, MSB32);
9361 movLeft2Result(left, LSB, result, MSB24);
9363 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9364 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9368 /* if more than 1 byte */
9369 else if ( shCount >= 8 ) {
9370 /* lower order three bytes goes to higher order three bytes */
9374 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9376 movLeft2Result(left, LSB, result, MSB16);
9378 else{ /* size = 4 */
9380 movLeft2Result(left, MSB24, result, MSB32);
9381 movLeft2Result(left, MSB16, result, MSB24);
9382 movLeft2Result(left, LSB, result, MSB16);
9383 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9385 else if(shCount == 1)
9386 shiftLLong(left, result, MSB16);
9388 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9389 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9390 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9391 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9396 /* 1 <= shCount <= 7 */
9397 else if(shCount <= 3)
9399 shiftLLong(left, result, LSB);
9400 while(--shCount >= 1)
9401 shiftLLong(result, result, LSB);
9403 /* 3 <= shCount <= 7, optimize */
9405 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9406 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9407 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9411 /*-----------------------------------------------------------------*/
9412 /* genLeftShiftLiteral - left shifting by known count */
9413 /*-----------------------------------------------------------------*/
9414 void pic16_genLeftShiftLiteral (operand *left,
9419 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9423 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9424 pic16_freeAsmop(right,NULL,ic,TRUE);
9426 pic16_aopOp(left,ic,FALSE);
9427 pic16_aopOp(result,ic,TRUE);
9429 size = getSize(operandType(result));
9432 pic16_emitcode("; shift left ","result %d, left %d",size,
9436 /* I suppose that the left size >= result size */
9439 movLeft2Result(left, size, result, size);
9443 else if(shCount >= (size * 8))
9445 pic16_aopPut(AOP(result),zero,size);
9449 genlshOne (result,left,shCount);
9454 genlshTwo (result,left,shCount);
9458 genlshFour (result,left,shCount);
9462 pic16_freeAsmop(left,NULL,ic,TRUE);
9463 pic16_freeAsmop(result,NULL,ic,TRUE);
9466 /*-----------------------------------------------------------------*
9467 * genMultiAsm - repeat assembly instruction for size of register.
9468 * if endian == 1, then the high byte (i.e base address + size of
9469 * register) is used first else the low byte is used first;
9470 *-----------------------------------------------------------------*/
9471 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9476 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9489 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9495 #if !(USE_GENERIC_SIGNED_SHIFT)
9496 /*-----------------------------------------------------------------*/
9497 /* genLeftShift - generates code for left shifting */
9498 /*-----------------------------------------------------------------*/
9499 static void genLeftShift (iCode *ic)
9501 operand *left,*right, *result;
9504 symbol *tlbl , *tlbl1;
9507 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9509 right = IC_RIGHT(ic);
9511 result = IC_RESULT(ic);
9513 pic16_aopOp(right,ic,FALSE);
9515 /* if the shift count is known then do it
9516 as efficiently as possible */
9517 if (AOP_TYPE(right) == AOP_LIT) {
9518 pic16_genLeftShiftLiteral (left,right,result,ic);
9522 /* shift count is unknown then we have to form
9523 * a loop. Get the loop count in WREG : Note: we take
9524 * only the lower order byte since shifting
9525 * more than 32 bits make no sense anyway, ( the
9526 * largest size of an object can be only 32 bits ) */
9528 pic16_aopOp(left,ic,FALSE);
9529 pic16_aopOp(result,ic,FALSE);
9531 /* now move the left to the result if they are not the
9532 * same, and if size > 1,
9533 * and if right is not same to result (!!!) -- VR */
9534 if (!pic16_sameRegs(AOP(left),AOP(result))
9535 && (AOP_SIZE(result) > 1)) {
9537 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9539 size = AOP_SIZE(result);
9544 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9545 if (*l == '@' && (IS_AOP_PREG(result))) {
9547 pic16_emitcode("mov","a,%s",l);
9548 pic16_aopPut(AOP(result),"a",offset);
9552 /* we don't know if left is a literal or a register, take care -- VR */
9553 pic16_mov2f(AOP(result), AOP(left), offset);
9559 size = AOP_SIZE(result);
9561 /* if it is only one byte then */
9563 if(optimized_for_speed) {
9564 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9565 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9566 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9567 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9568 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9569 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9570 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9571 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9572 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9573 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9574 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9575 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9578 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9580 tlbl = newiTempLabel(NULL);
9583 /* this is already done, why change it? */
9584 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9585 pic16_mov2f(AOP(result), AOP(left), 0);
9589 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9590 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9591 pic16_emitpLabel(tlbl->key);
9592 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9593 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9595 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9600 if (pic16_sameRegs(AOP(left),AOP(result))) {
9602 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9604 tlbl = newiTempLabel(NULL);
9605 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9606 genMultiAsm(POC_RRCF, result, size,1);
9607 pic16_emitpLabel(tlbl->key);
9608 genMultiAsm(POC_RLCF, result, size,0);
9609 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9611 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9615 //tlbl = newiTempLabel(NULL);
9617 //tlbl1 = newiTempLabel(NULL);
9619 //reAdjustPreg(AOP(result));
9621 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9622 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9623 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9625 //pic16_emitcode("add","a,acc");
9626 //pic16_aopPut(AOP(result),"a",offset++);
9628 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9630 // pic16_emitcode("rlc","a");
9631 // pic16_aopPut(AOP(result),"a",offset++);
9633 //reAdjustPreg(AOP(result));
9635 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9636 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9639 tlbl = newiTempLabel(NULL);
9640 tlbl1= newiTempLabel(NULL);
9642 size = AOP_SIZE(result);
9645 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9647 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9649 /* offset should be 0, 1 or 3 */
9651 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9653 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9655 pic16_emitpcode(POC_MOVWF, pctemp);
9658 pic16_emitpLabel(tlbl->key);
9661 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9663 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9665 pic16_emitpcode(POC_DECFSZ, pctemp);
9666 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9667 pic16_emitpLabel(tlbl1->key);
9669 pic16_popReleaseTempReg(pctemp,1);
9673 pic16_freeAsmop (right,NULL,ic,TRUE);
9674 pic16_freeAsmop(left,NULL,ic,TRUE);
9675 pic16_freeAsmop(result,NULL,ic,TRUE);
9681 #error old code (left here for reference)
9682 /*-----------------------------------------------------------------*/
9683 /* genLeftShift - generates code for left shifting */
9684 /*-----------------------------------------------------------------*/
9685 static void genLeftShift (iCode *ic)
9687 operand *left,*right, *result;
9690 symbol *tlbl , *tlbl1;
9693 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9695 right = IC_RIGHT(ic);
9697 result = IC_RESULT(ic);
9699 pic16_aopOp(right,ic,FALSE);
9701 /* if the shift count is known then do it
9702 as efficiently as possible */
9703 if (AOP_TYPE(right) == AOP_LIT) {
9704 pic16_genLeftShiftLiteral (left,right,result,ic);
9708 /* shift count is unknown then we have to form
9709 a loop get the loop count in B : Note: we take
9710 only the lower order byte since shifting
9711 more that 32 bits make no sense anyway, ( the
9712 largest size of an object can be only 32 bits ) */
9715 pic16_aopOp(left,ic,FALSE);
9716 pic16_aopOp(result,ic,FALSE);
9718 /* now move the left to the result if they are not the
9720 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9721 AOP_SIZE(result) > 1) {
9723 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9725 size = AOP_SIZE(result);
9728 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9729 if (*l == '@' && (IS_AOP_PREG(result))) {
9731 pic16_emitcode("mov","a,%s",l);
9732 pic16_aopPut(AOP(result),"a",offset);
9735 /* we don't know if left is a literal or a register, take care -- VR */
9736 pic16_mov2f(AOP(result), AOP(left), offset);
9742 size = AOP_SIZE(result);
9744 /* if it is only one byte then */
9746 if(optimized_for_speed) {
9747 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9748 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9749 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9750 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9751 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9752 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9753 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9754 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9755 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9756 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9757 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9758 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9761 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9763 tlbl = newiTempLabel(NULL);
9764 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9765 pic16_mov2f(AOP(result), AOP(left), 0);
9767 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9768 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9771 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9772 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9773 pic16_emitpLabel(tlbl->key);
9774 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9775 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9777 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9782 if (pic16_sameRegs(AOP(left),AOP(result))) {
9784 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9786 tlbl = newiTempLabel(NULL);
9787 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9788 genMultiAsm(POC_RRCF, result, size,1);
9789 pic16_emitpLabel(tlbl->key);
9790 genMultiAsm(POC_RLCF, result, size,0);
9791 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9793 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9797 //tlbl = newiTempLabel(NULL);
9799 //tlbl1 = newiTempLabel(NULL);
9801 //reAdjustPreg(AOP(result));
9803 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9804 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9805 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9807 //pic16_emitcode("add","a,acc");
9808 //pic16_aopPut(AOP(result),"a",offset++);
9810 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9812 // pic16_emitcode("rlc","a");
9813 // pic16_aopPut(AOP(result),"a",offset++);
9815 //reAdjustPreg(AOP(result));
9817 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9818 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9821 tlbl = newiTempLabel(NULL);
9822 tlbl1= newiTempLabel(NULL);
9824 size = AOP_SIZE(result);
9827 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9829 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9831 /* offset should be 0, 1 or 3 */
9833 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9835 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9837 pic16_emitpcode(POC_MOVWF, pctemp);
9840 pic16_emitpLabel(tlbl->key);
9843 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9845 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9847 pic16_emitpcode(POC_DECFSZ, pctemp);
9848 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9849 pic16_emitpLabel(tlbl1->key);
9851 pic16_popReleaseTempReg(pctemp,1);
9855 pic16_freeAsmop (right,NULL,ic,TRUE);
9856 pic16_freeAsmop(left,NULL,ic,TRUE);
9857 pic16_freeAsmop(result,NULL,ic,TRUE);
9861 /*-----------------------------------------------------------------*/
9862 /* genrshOne - right shift a one byte quantity by known count */
9863 /*-----------------------------------------------------------------*/
9864 static void genrshOne (operand *result, operand *left,
9865 int shCount, int sign)
9867 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9868 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9871 /*-----------------------------------------------------------------*/
9872 /* genrshTwo - right shift two bytes by known amount != 0 */
9873 /*-----------------------------------------------------------------*/
9874 static void genrshTwo (operand *result,operand *left,
9875 int shCount, int sign)
9877 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9878 /* if shCount >= 8 */
9882 shiftR1Left2Result(left, MSB16, result, LSB,
9885 movLeft2Result(left, MSB16, result, LSB);
9887 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9890 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9891 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),MSB16));
9895 /* 1 <= shCount <= 7 */
9897 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9900 /*-----------------------------------------------------------------*/
9901 /* shiftRLong - shift right one long from left to result */
9902 /* offl = LSB or MSB16 */
9903 /*-----------------------------------------------------------------*/
9904 static void shiftRLong (operand *left, int offl,
9905 operand *result, int sign)
9907 int size = AOP_SIZE(result);
9908 int same = pic16_sameRegs(AOP(left),AOP(result));
9910 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9912 if (same && (offl == MSB16)) { //shift one byte right
9913 for(i=MSB16;i<size;i++) {
9914 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9915 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9920 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9926 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9928 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9929 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9933 /* add sign of "a" */
9934 pic16_addSign(result, MSB32, sign);
9938 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9940 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9941 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9945 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9947 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9948 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9952 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9955 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9956 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9961 /*-----------------------------------------------------------------*/
9962 /* genrshFour - shift four byte by a known amount != 0 */
9963 /*-----------------------------------------------------------------*/
9964 static void genrshFour (operand *result, operand *left,
9965 int shCount, int sign)
9967 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9968 /* if shifting more that 3 bytes */
9969 if(shCount >= 24 ) {
9972 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9974 movLeft2Result(left, MSB32, result, LSB);
9976 pic16_addSign(result, MSB16, sign);
9978 else if(shCount >= 16){
9981 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9983 movLeft2Result(left, MSB24, result, LSB);
9984 movLeft2Result(left, MSB32, result, MSB16);
9986 pic16_addSign(result, MSB24, sign);
9988 else if(shCount >= 8){
9991 shiftRLong(left, MSB16, result, sign);
9992 else if(shCount == 0){
9993 movLeft2Result(left, MSB16, result, LSB);
9994 movLeft2Result(left, MSB24, result, MSB16);
9995 movLeft2Result(left, MSB32, result, MSB24);
9996 pic16_addSign(result, MSB32, sign);
9998 else{ //shcount >= 2
9999 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10000 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10001 /* the last shift is signed */
10002 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10003 pic16_addSign(result, MSB32, sign);
10006 else{ /* 1 <= shCount <= 7 */
10008 shiftRLong(left, LSB, result, sign);
10010 shiftRLong(result, LSB, result, sign);
10013 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10014 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10015 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10020 /*-----------------------------------------------------------------*/
10021 /* genRightShiftLiteral - right shifting by known count */
10022 /*-----------------------------------------------------------------*/
10023 static void genRightShiftLiteral (operand *left,
10029 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10030 int lsize,res_size;
10032 pic16_freeAsmop(right,NULL,ic,TRUE);
10034 pic16_aopOp(left,ic,FALSE);
10035 pic16_aopOp(result,ic,TRUE);
10037 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10040 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10044 lsize = pic16_getDataSize(left);
10045 res_size = pic16_getDataSize(result);
10046 /* test the LEFT size !!! */
10048 /* I suppose that the left size >= result size */
10050 assert (res_size <= lsize);
10051 while (res_size--) {
10052 pic16_mov2f (AOP(result), AOP(left), res_size);
10056 else if(shCount >= (lsize * 8)){
10058 if(res_size == 1) {
10059 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10061 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10062 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10067 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10068 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10069 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10071 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10076 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10081 switch (res_size) {
10083 genrshOne (result,left,shCount,sign);
10087 genrshTwo (result,left,shCount,sign);
10091 genrshFour (result,left,shCount,sign);
10099 pic16_freeAsmop(left,NULL,ic,TRUE);
10100 pic16_freeAsmop(result,NULL,ic,TRUE);
10103 #if !(USE_GENERIC_SIGNED_SHIFT)
10104 /*-----------------------------------------------------------------*/
10105 /* genSignedRightShift - right shift of signed number */
10106 /*-----------------------------------------------------------------*/
10107 static void genSignedRightShift (iCode *ic)
10109 operand *right, *left, *result;
10112 symbol *tlbl, *tlbl1 ;
10115 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10117 /* we do it the hard way put the shift count in b
10118 and loop thru preserving the sign */
10119 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10121 right = IC_RIGHT(ic);
10122 left = IC_LEFT(ic);
10123 result = IC_RESULT(ic);
10125 pic16_aopOp(right,ic,FALSE);
10126 pic16_aopOp(left,ic,FALSE);
10127 pic16_aopOp(result,ic,FALSE);
10130 if ( AOP_TYPE(right) == AOP_LIT) {
10131 genRightShiftLiteral (left,right,result,ic,1);
10134 /* shift count is unknown then we have to form
10135 a loop get the loop count in B : Note: we take
10136 only the lower order byte since shifting
10137 more that 32 bits make no sense anyway, ( the
10138 largest size of an object can be only 32 bits ) */
10140 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10141 //pic16_emitcode("inc","b");
10142 //pic16_freeAsmop (right,NULL,ic,TRUE);
10143 //pic16_aopOp(left,ic,FALSE);
10144 //pic16_aopOp(result,ic,FALSE);
10146 /* now move the left to the result if they are not the
10148 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10149 AOP_SIZE(result) > 1) {
10151 size = AOP_SIZE(result);
10155 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10156 if (*l == '@' && IS_AOP_PREG(result)) {
10158 pic16_emitcode("mov","a,%s",l);
10159 pic16_aopPut(AOP(result),"a",offset);
10161 pic16_aopPut(AOP(result),l,offset);
10163 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10164 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10170 /* mov the highest order bit to OVR */
10171 tlbl = newiTempLabel(NULL);
10172 tlbl1= newiTempLabel(NULL);
10174 size = AOP_SIZE(result);
10177 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10179 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10181 /* offset should be 0, 1 or 3 */
10182 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10184 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10186 pic16_emitpcode(POC_MOVWF, pctemp);
10189 pic16_emitpLabel(tlbl->key);
10191 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10192 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10195 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10198 pic16_emitpcode(POC_DECFSZ, pctemp);
10199 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10200 pic16_emitpLabel(tlbl1->key);
10202 pic16_popReleaseTempReg(pctemp,1);
10204 size = AOP_SIZE(result);
10206 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10207 pic16_emitcode("rlc","a");
10208 pic16_emitcode("mov","ov,c");
10209 /* if it is only one byte then */
10211 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10213 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10214 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10215 pic16_emitcode("mov","c,ov");
10216 pic16_emitcode("rrc","a");
10217 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10218 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10219 pic16_aopPut(AOP(result),"a",0);
10223 reAdjustPreg(AOP(result));
10224 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10225 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10226 pic16_emitcode("mov","c,ov");
10228 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10230 pic16_emitcode("rrc","a");
10231 pic16_aopPut(AOP(result),"a",offset--);
10233 reAdjustPreg(AOP(result));
10234 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10235 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10240 pic16_freeAsmop(left,NULL,ic,TRUE);
10241 pic16_freeAsmop(result,NULL,ic,TRUE);
10242 pic16_freeAsmop(right,NULL,ic,TRUE);
10246 #if !(USE_GENERIC_SIGNED_SHIFT)
10247 #warning This implementation of genRightShift() is incomplete!
10248 /*-----------------------------------------------------------------*/
10249 /* genRightShift - generate code for right shifting */
10250 /*-----------------------------------------------------------------*/
10251 static void genRightShift (iCode *ic)
10253 operand *right, *left, *result;
10257 symbol *tlbl, *tlbl1 ;
10259 /* if signed then we do it the hard way preserve the
10260 sign bit moving it inwards */
10261 letype = getSpec(operandType(IC_LEFT(ic)));
10262 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10264 if (!SPEC_USIGN(letype)) {
10265 genSignedRightShift (ic);
10269 /* signed & unsigned types are treated the same : i.e. the
10270 signed is NOT propagated inwards : quoting from the
10271 ANSI - standard : "for E1 >> E2, is equivalent to division
10272 by 2**E2 if unsigned or if it has a non-negative value,
10273 otherwise the result is implementation defined ", MY definition
10274 is that the sign does not get propagated */
10276 right = IC_RIGHT(ic);
10277 left = IC_LEFT(ic);
10278 result = IC_RESULT(ic);
10280 pic16_aopOp(right,ic,FALSE);
10282 /* if the shift count is known then do it
10283 as efficiently as possible */
10284 if (AOP_TYPE(right) == AOP_LIT) {
10285 genRightShiftLiteral (left,right,result,ic, 0);
10289 /* shift count is unknown then we have to form
10290 a loop get the loop count in B : Note: we take
10291 only the lower order byte since shifting
10292 more that 32 bits make no sense anyway, ( the
10293 largest size of an object can be only 32 bits ) */
10295 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10296 pic16_emitcode("inc","b");
10297 pic16_aopOp(left,ic,FALSE);
10298 pic16_aopOp(result,ic,FALSE);
10300 /* now move the left to the result if they are not the
10302 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10303 AOP_SIZE(result) > 1) {
10305 size = AOP_SIZE(result);
10308 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10309 if (*l == '@' && IS_AOP_PREG(result)) {
10311 pic16_emitcode("mov","a,%s",l);
10312 pic16_aopPut(AOP(result),"a",offset);
10314 pic16_aopPut(AOP(result),l,offset);
10319 tlbl = newiTempLabel(NULL);
10320 tlbl1= newiTempLabel(NULL);
10321 size = AOP_SIZE(result);
10324 /* if it is only one byte then */
10327 tlbl = newiTempLabel(NULL);
10328 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10329 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10330 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10333 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10334 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10335 pic16_emitpLabel(tlbl->key);
10336 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10337 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10339 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10344 reAdjustPreg(AOP(result));
10345 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10346 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10349 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10351 pic16_emitcode("rrc","a");
10352 pic16_aopPut(AOP(result),"a",offset--);
10354 reAdjustPreg(AOP(result));
10356 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10357 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10360 pic16_freeAsmop(left,NULL,ic,TRUE);
10361 pic16_freeAsmop (right,NULL,ic,TRUE);
10362 pic16_freeAsmop(result,NULL,ic,TRUE);
10366 #if (USE_GENERIC_SIGNED_SHIFT)
10367 /*-----------------------------------------------------------------*/
10368 /* genGenericShift - generates code for left or right shifting */
10369 /*-----------------------------------------------------------------*/
10370 static void genGenericShift (iCode *ic, int isShiftLeft) {
10371 operand *left,*right, *result;
10373 int sign, signedCount;
10374 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10375 PIC_OPCODE pos_shift, neg_shift;
10379 right = IC_RIGHT(ic);
10380 left = IC_LEFT(ic);
10381 result = IC_RESULT(ic);
10383 pic16_aopOp(right,ic,FALSE);
10384 pic16_aopOp(left,ic,FALSE);
10385 pic16_aopOp(result,ic,TRUE);
10387 sign = !SPEC_USIGN(operandType (left));
10388 signedCount = !SPEC_USIGN(operandType (right));
10390 /* if the shift count is known then do it
10391 as efficiently as possible */
10392 if (AOP_TYPE(right) == AOP_LIT) {
10393 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10394 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10395 // we should modify right->aopu.aop_lit here!
10396 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10397 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10399 pic16_genLeftShiftLiteral (left,right,result,ic);
10401 genRightShiftLiteral (left,right,result,ic, sign);
10404 } // if (right is literal)
10406 /* shift count is unknown then we have to form a loop.
10407 * Note: we take only the lower order byte since shifting
10408 * more than 32 bits make no sense anyway, ( the
10409 * largest size of an object can be only 32 bits )
10410 * Note: we perform arithmetic shifts if the left operand is
10411 * signed and we do an (effective) right shift, i. e. we
10412 * shift in the sign bit from the left. */
10414 label_complete = newiTempLabel ( NULL );
10415 label_loop_pos = newiTempLabel ( NULL );
10416 label_loop_neg = NULL;
10417 label_negative = NULL;
10418 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10419 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10422 // additional labels needed
10423 label_loop_neg = newiTempLabel ( NULL );
10424 label_negative = newiTempLabel ( NULL );
10427 // copy source to result -- this will effectively truncate the left operand to the size of result!
10428 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10429 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10430 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10431 pic16_mov2f (AOP(result),AOP(left), offset);
10434 // if result is longer than left, fill with zeros (or sign)
10435 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10436 if (sign && AOP_SIZE(left) > 0) {
10437 // shift signed operand -- fill with sign
10438 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10439 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10440 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10441 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10442 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10445 // shift unsigned operand -- fill result with zeros
10446 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10447 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10450 } // if (size mismatch)
10452 pic16_mov2w (AOP(right), 0);
10453 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10454 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10457 // perform a shift by one (shift count is positive)
10458 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10459 // 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])
10460 pic16_emitpLabel (label_loop_pos->key);
10462 if (sign && (pos_shift == POC_RRCF)) {
10463 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10466 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10467 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10468 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10470 // perform a shift by one (shift count is positive)
10471 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10472 // 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])
10473 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10474 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10476 pic16_emitpLabel (label_loop_pos->key);
10477 if (sign && (pos_shift == POC_RRCF)) {
10478 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10481 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10482 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10483 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10484 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10488 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10490 pic16_emitpLabel (label_negative->key);
10491 // perform a shift by -1 (shift count is negative)
10492 // 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)
10494 pic16_emitpLabel (label_loop_neg->key);
10495 if (sign && (neg_shift == POC_RRCF)) {
10496 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10499 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10500 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10501 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10502 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10503 } // if (signedCount)
10505 pic16_emitpLabel (label_complete->key);
10508 pic16_freeAsmop (right,NULL,ic,TRUE);
10509 pic16_freeAsmop(left,NULL,ic,TRUE);
10510 pic16_freeAsmop(result,NULL,ic,TRUE);
10513 static void genLeftShift (iCode *ic) {
10514 genGenericShift (ic, 1);
10517 static void genRightShift (iCode *ic) {
10518 genGenericShift (ic, 0);
10523 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10524 void pic16_loadFSR0(operand *op, int lit)
10526 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10527 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10529 assert (!OP_SYMBOL(op)->remat);
10530 // set up FSR0 with address of result
10531 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10532 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10536 /*-----------------------------------------------------------------*/
10537 /* genUnpackBits - generates code for unpacking bits */
10538 /*-----------------------------------------------------------------*/
10539 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10543 sym_link *etype, *letype;
10544 int blen=0, bstr=0;
10548 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10549 etype = getSpec(operandType(result));
10550 letype = getSpec(operandType(left));
10552 // if(IS_BITFIELD(etype)) {
10553 blen = SPEC_BLEN(etype);
10554 bstr = SPEC_BSTR(etype);
10557 lbstr = SPEC_BSTR( letype );
10560 if((blen == 1) && (bstr < 8)) {
10561 /* it is a single bit, so use the appropriate bit instructions */
10562 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10564 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10566 // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10567 if(OP_SYMBOL(left)->remat && (ptype == POINTER) && (result)) {
10568 /* workaround to reduce the extra lfsr instruction */
10569 pic16_emitpcode(POC_BTFSC,
10570 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10572 pic16_loadFSR0 (left, 0);
10573 pic16_emitpcode(POC_BTFSC,
10574 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10577 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10579 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10585 /* the following call to pic16_loadFSR0 is temporary until
10586 * optimization to handle single bit assignments is added
10587 * to the function. Until then use the old safe way! -- VR */
10589 if (OP_SYMBOL(left)->remat) {
10590 // access symbol directly
10591 pic16_mov2w (AOP(left), 0);
10593 pic16_loadFSR0( left, 0 );
10595 /* read the first byte */
10602 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10605 pic16_emitcode("clr","a");
10606 pic16_emitcode("movc","a","@a+dptr");
10612 /* if we have bitdisplacement then it fits */
10613 /* into this byte completely or if length is */
10614 /* less than a byte */
10615 if ((shCnt = SPEC_BSTR(etype)) ||
10616 (SPEC_BLEN(etype) <= 8)) {
10618 /* shift right acc */
10621 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10622 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10624 /* VR -- normally I would use the following, but since we use the hack,
10625 * to avoid the masking from AccRsh, why not mask it right now? */
10628 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10631 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10637 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10638 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10641 /* bit field did not fit in a byte */
10642 rlen = SPEC_BLEN(etype) - 8;
10643 pic16_aopPut(AOP(result),"a",offset++);
10650 pic16_emitcode("inc","%s",rname);
10651 pic16_emitcode("mov","a,@%s",rname);
10655 pic16_emitcode("inc","%s",rname);
10656 pic16_emitcode("movx","a,@%s",rname);
10660 pic16_emitcode("inc","dptr");
10661 pic16_emitcode("movx","a,@dptr");
10665 pic16_emitcode("clr","a");
10666 pic16_emitcode("inc","dptr");
10667 pic16_emitcode("movc","a","@a+dptr");
10671 pic16_emitcode("inc","dptr");
10672 pic16_emitcode("lcall","__gptrget");
10677 /* if we are done */
10681 pic16_aopPut(AOP(result),"a",offset++);
10686 pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
10687 pic16_aopPut(AOP(result),"a",offset);
10694 static void genDataPointerGet(operand *left,
10698 int size, offset = 0, leoffset=0 ;
10700 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10701 pic16_aopOp(result, ic, TRUE);
10705 size = AOP_SIZE(result);
10706 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10710 /* The following tests may save a redudant movff instruction when
10711 * accessing unions */
10713 /* if they are the same */
10714 if (operandsEqu (left, result)) {
10715 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10721 /* if they are the same registers */
10722 if (pic16_sameRegs(AOP(left),AOP(result))) {
10723 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10729 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10730 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10731 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10738 if ( AOP_TYPE(left) == AOP_PCODE) {
10739 fprintf(stderr,"genDataPointerGet %s, %d\n",
10740 AOP(left)->aopu.pcop->name,
10741 (AOP(left)->aopu.pcop->type == PO_DIR)?
10742 PCOR(AOP(left)->aopu.pcop)->instance:
10743 PCOI(AOP(left)->aopu.pcop)->offset);
10747 if(AOP(left)->aopu.pcop->type == PO_DIR)
10748 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10750 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10753 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10755 // pic16_DumpOp("(result)",result);
10756 if(is_LitAOp(AOP(result))) {
10757 pic16_mov2w(AOP(left), offset); // patch 8
10758 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10760 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10761 pic16_popGet(AOP(left), offset), //patch 8
10762 pic16_popGet(AOP(result), offset)));
10770 pic16_freeAsmop(result,NULL,ic,TRUE);
10775 /*-----------------------------------------------------------------*/
10776 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10777 /*-----------------------------------------------------------------*/
10778 static void genNearPointerGet (operand *left,
10782 // asmop *aop = NULL;
10783 //regs *preg = NULL ;
10784 sym_link *rtype, *retype;
10785 sym_link *ltype = operandType(left);
10789 rtype = operandType(result);
10790 retype= getSpec(rtype);
10792 pic16_aopOp(left,ic,FALSE);
10794 // pic16_DumpOp("(left)",left);
10795 // pic16_DumpOp("(result)",result);
10797 /* if left is rematerialisable and
10798 * result is not bit variable type and
10799 * the left is pointer to data space i.e
10800 * lower 128 bytes of space */
10802 if (AOP_TYPE(left) == AOP_PCODE
10803 && !IS_BITFIELD(retype)
10804 && DCL_TYPE(ltype) == POINTER) {
10806 genDataPointerGet (left,result,ic);
10807 pic16_freeAsmop(left, NULL, ic, TRUE);
10811 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10812 pic16_aopOp (result,ic,TRUE);
10814 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10817 if(IS_BITFIELD( retype )
10818 && (SPEC_BLEN(operandType(result))==1)
10822 int bitstrt, bytestrt;
10824 /* if this is bitfield of size 1, see if we are checking the value
10825 * of a single bit in an if-statement,
10826 * if yes, then don't generate usual code, but execute the
10827 * genIfx directly -- VR */
10831 /* CHECK: if next iCode is IFX
10832 * and current result operand is nextic's conditional operand
10833 * and current result operand live ranges ends at nextic's key number
10835 if((nextic->op == IFX)
10836 && (result == IC_COND(nextic))
10837 && (OP_LIVETO(result) == nextic->seq)
10838 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10840 /* everything is ok then */
10841 /* find a way to optimize the genIfx iCode */
10843 bytestrt = SPEC_BSTR(operandType(result))/8;
10844 bitstrt = SPEC_BSTR(operandType(result))%8;
10846 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10848 genIfxpCOpJump(nextic, jop);
10850 pic16_freeAsmop(left, NULL, ic, TRUE);
10851 pic16_freeAsmop(result, NULL, ic, TRUE);
10858 /* if the value is already in a pointer register
10859 * then don't need anything more */
10860 if (1 || !AOP_INPREG(AOP(left))) { // AOP_INPREG(AOP(left)) is not always correct...
10861 /* otherwise get a free pointer register */
10862 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10867 /* if bitfield then unpack the bits */
10868 if (IS_BITFIELD(retype))
10869 genUnpackBits (result, left, NULL, POINTER);
10871 /* we have can just get the values */
10872 int size = AOP_SIZE(result);
10875 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10877 pic16_loadFSR0( left, 0 );
10881 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10882 pic16_popGet(AOP(result), offset++)));
10884 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10885 pic16_popGet(AOP(result), offset++)));
10891 /* now some housekeeping stuff */
10893 /* we had to allocate for this iCode */
10894 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
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 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10903 if (AOP_SIZE(result) > 1
10904 && !OP_SYMBOL(left)->remat
10905 && ( OP_SYMBOL(left)->liveTo > ic->seq
10907 // int size = AOP_SIZE(result) - 1;
10909 // pic16_emitcode("dec","%s",rname);
10915 pic16_freeAsmop(left,NULL,ic,TRUE);
10916 pic16_freeAsmop(result,NULL,ic,TRUE);
10919 /*-----------------------------------------------------------------*/
10920 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10921 /*-----------------------------------------------------------------*/
10922 static void genPagedPointerGet (operand *left,
10927 regs *preg = NULL ;
10929 sym_link *rtype, *retype;
10931 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10933 rtype = operandType(result);
10934 retype= getSpec(rtype);
10936 pic16_aopOp(left,ic,FALSE);
10938 /* if the value is already in a pointer register
10939 then don't need anything more */
10940 if (!AOP_INPREG(AOP(left))) {
10941 /* otherwise get a free pointer register */
10943 preg = getFreePtr(ic,&aop,FALSE);
10944 pic16_emitcode("mov","%s,%s",
10946 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10947 rname = preg->name ;
10949 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10951 pic16_freeAsmop(left,NULL,ic,TRUE);
10952 pic16_aopOp (result,ic,TRUE);
10954 /* if bitfield then unpack the bits */
10955 if (IS_BITFIELD(retype))
10956 genUnpackBits (result,left,rname,PPOINTER);
10958 /* we have can just get the values */
10959 int size = AOP_SIZE(result);
10964 pic16_emitcode("movx","a,@%s",rname);
10965 pic16_aopPut(AOP(result),"a",offset);
10970 pic16_emitcode("inc","%s",rname);
10974 /* now some housekeeping stuff */
10976 /* we had to allocate for this iCode */
10977 pic16_freeAsmop(NULL,aop,ic,TRUE);
10979 /* we did not allocate which means left
10980 already in a pointer register, then
10981 if size > 0 && this could be used again
10982 we have to point it back to where it
10984 if (AOP_SIZE(result) > 1 &&
10985 !OP_SYMBOL(left)->remat &&
10986 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10988 int size = AOP_SIZE(result) - 1;
10990 pic16_emitcode("dec","%s",rname);
10995 pic16_freeAsmop(result,NULL,ic,TRUE);
11000 /*-----------------------------------------------------------------*/
11001 /* genFarPointerGet - gget value from far space */
11002 /*-----------------------------------------------------------------*/
11003 static void genFarPointerGet (operand *left,
11004 operand *result, iCode *ic)
11007 sym_link *retype = getSpec(operandType(result));
11009 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11011 pic16_aopOp(left,ic,FALSE);
11013 /* if the operand is already in dptr
11014 then we do nothing else we move the value to dptr */
11015 if (AOP_TYPE(left) != AOP_STR) {
11016 /* if this is remateriazable */
11017 if (AOP_TYPE(left) == AOP_IMMD)
11018 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11019 else { /* we need to get it byte by byte */
11020 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11021 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11022 if (options.model == MODEL_FLAT24)
11024 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11028 /* so dptr know contains the address */
11029 pic16_freeAsmop(left,NULL,ic,TRUE);
11030 pic16_aopOp(result,ic,TRUE);
11032 /* if bit then unpack */
11033 if (IS_BITFIELD(retype))
11034 genUnpackBits(result,left,"dptr",FPOINTER);
11036 size = AOP_SIZE(result);
11040 pic16_emitcode("movx","a,@dptr");
11041 pic16_aopPut(AOP(result),"a",offset++);
11043 pic16_emitcode("inc","dptr");
11047 pic16_freeAsmop(result,NULL,ic,TRUE);
11051 /*-----------------------------------------------------------------*/
11052 /* genCodePointerGet - get value from code space */
11053 /*-----------------------------------------------------------------*/
11054 static void genCodePointerGet (operand *left,
11055 operand *result, iCode *ic)
11058 sym_link *retype = getSpec(operandType(result));
11060 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11062 pic16_aopOp(left,ic,FALSE);
11064 /* if the operand is already in dptr
11065 then we do nothing else we move the value to dptr */
11066 if (AOP_TYPE(left) != AOP_STR) {
11067 /* if this is remateriazable */
11068 if (AOP_TYPE(left) == AOP_IMMD)
11069 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11070 else { /* we need to get it byte by byte */
11071 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11072 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11073 if (options.model == MODEL_FLAT24)
11075 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11079 /* so dptr know contains the address */
11080 pic16_freeAsmop(left,NULL,ic,TRUE);
11081 pic16_aopOp(result,ic,FALSE);
11083 /* if bit then unpack */
11084 if (IS_BITFIELD(retype))
11085 genUnpackBits(result,left,"dptr",CPOINTER);
11087 size = AOP_SIZE(result);
11091 pic16_emitcode("clr","a");
11092 pic16_emitcode("movc","a,@a+dptr");
11093 pic16_aopPut(AOP(result),"a",offset++);
11095 pic16_emitcode("inc","dptr");
11099 pic16_freeAsmop(result,NULL,ic,TRUE);
11104 /*-----------------------------------------------------------------*/
11105 /* genGenPointerGet - gget value from generic pointer space */
11106 /*-----------------------------------------------------------------*/
11107 static void genGenPointerGet (operand *left,
11108 operand *result, iCode *ic)
11110 int size, offset, lit;
11111 sym_link *retype = getSpec(operandType(result));
11113 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11114 pic16_aopOp(left,ic,FALSE);
11115 pic16_aopOp(result,ic,FALSE);
11116 size = AOP_SIZE(result);
11118 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11120 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11122 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11123 // load FSR0 from immediate
11124 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11126 // pic16_loadFSR0( left );
11131 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11133 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11140 else { /* we need to get it byte by byte */
11141 // set up FSR0 with address from left
11142 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11143 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11149 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11151 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11158 /* if bit then unpack */
11159 if (IS_BITFIELD(retype))
11160 genUnpackBits(result,left,"BAD",GPOINTER);
11163 pic16_freeAsmop(left,NULL,ic,TRUE);
11164 pic16_freeAsmop(result,NULL,ic,TRUE);
11170 /*-----------------------------------------------------------------*/
11171 /* genGenPointerGet - gget value from generic pointer space */
11172 /*-----------------------------------------------------------------*/
11173 static void genGenPointerGet (operand *left,
11174 operand *result, iCode *ic)
11176 int size, offset, lit;
11177 sym_link *retype = getSpec(operandType(result));
11179 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11180 pic16_aopOp(left,ic,FALSE);
11181 pic16_aopOp(result,ic,TRUE);
11182 size = AOP_SIZE(result);
11184 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11186 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11188 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11189 // load FSR0 from immediate
11190 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11192 werror(W_POSSBUG2, __FILE__, __LINE__);
11197 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11199 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11206 } else { /* we need to get it byte by byte */
11208 /* set up WREG:PRODL:FSR0L with address from left */
11209 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11210 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11211 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11213 pic16_callGenericPointerRW(0, size);
11215 assignResultValue(result, 1);
11220 /* if bit then unpack */
11221 if (IS_BITFIELD(retype))
11222 genUnpackBits(result,left,"BAD",GPOINTER);
11225 pic16_freeAsmop(left,NULL,ic,TRUE);
11226 pic16_freeAsmop(result,NULL,ic,TRUE);
11229 /*-----------------------------------------------------------------*/
11230 /* genConstPointerGet - get value from const generic pointer space */
11231 /*-----------------------------------------------------------------*/
11232 static void genConstPointerGet (operand *left,
11233 operand *result, iCode *ic)
11235 //sym_link *retype = getSpec(operandType(result));
11236 // symbol *albl = newiTempLabel(NULL); // patch 15
11237 // symbol *blbl = newiTempLabel(NULL); //
11238 // PIC_OPCODE poc; // patch 15
11242 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11243 pic16_aopOp(left,ic,FALSE);
11244 pic16_aopOp(result,ic,TRUE);
11245 size = AOP_SIZE(result);
11247 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11249 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11251 // set up table pointer
11252 if( (AOP_TYPE(left) == AOP_PCODE)
11253 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11254 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11256 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11257 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11258 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11259 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11260 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11261 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11263 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11264 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11265 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11269 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11270 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11274 pic16_freeAsmop(left,NULL,ic,TRUE);
11275 pic16_freeAsmop(result,NULL,ic,TRUE);
11279 /*-----------------------------------------------------------------*/
11280 /* genPointerGet - generate code for pointer get */
11281 /*-----------------------------------------------------------------*/
11282 static void genPointerGet (iCode *ic)
11284 operand *left, *result ;
11285 sym_link *type, *etype;
11290 left = IC_LEFT(ic);
11291 result = IC_RESULT(ic) ;
11293 /* depending on the type of pointer we need to
11294 move it to the correct pointer register */
11295 type = operandType(left);
11296 etype = getSpec(type);
11299 if (IS_PTR_CONST(type))
11301 if (IS_CODEPTR(type))
11303 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11305 /* if left is of type of pointer then it is simple */
11306 if (IS_PTR(type) && !IS_FUNC(type->next))
11307 p_type = DCL_TYPE(type);
11309 /* we have to go by the storage class */
11310 p_type = PTR_TYPE(SPEC_OCLS(etype));
11312 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11314 if (SPEC_OCLS(etype)->codesp ) {
11315 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11316 //p_type = CPOINTER ;
11318 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11319 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11320 /*p_type = FPOINTER ;*/
11322 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11323 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11324 /* p_type = PPOINTER; */
11326 if (SPEC_OCLS(etype) == idata ) {
11327 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11328 /* p_type = IPOINTER; */
11330 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11331 /* p_type = POINTER ; */
11335 /* now that we have the pointer type we assign
11336 the pointer values */
11340 genNearPointerGet (left,result,ic);
11344 genPagedPointerGet(left,result,ic);
11348 genFarPointerGet (left,result,ic);
11352 genConstPointerGet (left,result,ic);
11353 //pic16_emitcodePointerGet (left,result,ic);
11358 if (IS_PTR_CONST(type))
11359 genConstPointerGet (left,result,ic);
11362 genGenPointerGet (left,result,ic);
11366 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11367 "genPointerGet: illegal pointer type");
11372 /*-----------------------------------------------------------------*/
11373 /* genPackBits - generates code for packed bit storage */
11374 /*-----------------------------------------------------------------*/
11375 static void genPackBits (sym_link *etype , operand *result,
11377 char *rname, int p_type)
11385 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11386 blen = SPEC_BLEN(etype);
11387 bstr = SPEC_BSTR(etype);
11389 retype = getSpec(operandType(right));
11391 if(AOP_TYPE(right) == AOP_LIT) {
11392 if((blen == 1) && (bstr < 8)) {
11394 /* it is a single bit, so use the appropriate bit instructions */
11396 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11398 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11399 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11400 if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11401 /* workaround to reduce the extra lfsr instruction */
11403 pic16_emitpcode(POC_BSF,
11404 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11406 pic16_emitpcode(POC_BCF,
11407 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11410 pic16_loadFSR0(result, 0);
11412 pic16_emitpcode(POC_BSF,
11413 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11415 pic16_emitpcode(POC_BCF,
11416 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11422 /* move literal to W */
11423 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11426 if(IS_BITFIELD(retype)
11427 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11431 rblen = SPEC_BLEN( retype );
11432 rbstr = SPEC_BSTR( retype );
11435 if(IS_BITFIELD(etype)) {
11436 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11437 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11439 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11442 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11444 if(IS_BITFIELD(etype)) {
11445 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11447 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11450 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11454 /* move right to W */
11455 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11458 /* if the bit length is less than or */
11459 /* it exactly fits a byte then */
11460 if((shCnt=SPEC_BSTR(etype))
11461 || SPEC_BLEN(etype) <= 8 ) {
11462 int fsr0_setup = 0;
11464 if (blen != 8 || bstr != 0) {
11465 // we need to combine the value with the old value
11466 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11468 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11469 SPEC_BSTR(etype), SPEC_BLEN(etype));
11471 /* shift left acc */
11474 /* using PRODH as a temporary register here */
11475 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11477 if (OP_SYMBOL(result)->remat) {
11478 // access symbol directly
11479 pic16_mov2w (AOP(result), 0);
11481 /* get old value */
11485 pic16_loadFSR0( result, 0 );
11487 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11488 // pic16_emitcode ("mov","b,a");
11489 // pic16_emitcode("mov","a,@%s",rname);
11493 if (AOP(result)->aopu.aop_reg[2]) {
11494 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
11495 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11496 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11497 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11499 pic16_callGenericPointerRW(0, 1);
11501 // data pointer (just 2 byte given)
11502 pic16_loadFSR0( result, 0 );
11504 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11507 // warnings will be emitted below
11508 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER...");
11509 //werror(W_POSSBUG2, __FILE__, __LINE__);
11513 assert (0 && "invalid pointer type specified");
11518 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11519 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11520 (unsigned char)(0xff >> (8-bstr))) ));
11521 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11522 } // if (blen != 8 || bstr != 0)
11524 /* write new value back */
11525 if (OP_SYMBOL(result)->remat) {
11526 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11531 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11532 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11536 if (AOP(result)->aopu.aop_reg[2]) {
11537 // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?)
11538 pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/));
11539 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11540 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl)));
11541 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2));
11543 pic16_callGenericPointerRW(1, 1);
11545 // data pointer (just 2 byte given)
11546 if (!fsr0_setup) pic16_loadFSR0( result, 0 );
11547 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11550 // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY)
11551 //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access");
11552 werror(W_POSSBUG2, __FILE__, __LINE__);
11556 assert (0 && "invalid pointer type specified");
11567 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11568 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11573 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11574 rLen = SPEC_BLEN(etype)-8;
11576 /* now generate for lengths greater than one byte */
11580 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11586 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11592 pic16_emitcode("movx","@dptr,a");
11597 DEBUGpic16_emitcode(";lcall","__gptrput");
11605 pic16_mov2w(AOP(right), offset++);
11608 /* last last was not complete */
11610 /* save the byte & read byte */
11613 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11614 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11619 pic16_emitcode ("mov","b,a");
11620 pic16_emitcode("movx","a,@dptr");
11624 pic16_emitcode ("push","b");
11625 pic16_emitcode ("push","acc");
11626 pic16_emitcode ("lcall","__gptrget");
11627 pic16_emitcode ("pop","b");
11633 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11634 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11635 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11636 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11637 // pic16_emitcode ("orl","a,b");
11640 // if (p_type == GPOINTER)
11641 // pic16_emitcode("pop","b");
11646 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11647 // pic16_emitcode("mov","@%s,a",rname);
11651 pic16_emitcode("movx","@dptr,a");
11655 DEBUGpic16_emitcode(";lcall","__gptrput");
11662 // pic16_freeAsmop(right, NULL, ic, TRUE);
11664 /*-----------------------------------------------------------------*/
11665 /* genDataPointerSet - remat pointer to data space */
11666 /*-----------------------------------------------------------------*/
11667 static void genDataPointerSet(operand *right,
11671 int size, offset = 0, resoffset=0 ;
11673 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11674 pic16_aopOp(right,ic,FALSE);
11676 size = AOP_SIZE(right);
11678 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11681 if ( AOP_TYPE(result) == AOP_PCODE) {
11682 fprintf(stderr,"genDataPointerSet %s, %d\n",
11683 AOP(result)->aopu.pcop->name,
11684 (AOP(result)->aopu.pcop->type == PO_DIR)?
11685 PCOR(AOP(result)->aopu.pcop)->instance:
11686 PCOI(AOP(result)->aopu.pcop)->offset);
11690 if(AOP(result)->aopu.pcop->type == PO_DIR)
11691 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11694 if (AOP_TYPE(right) == AOP_LIT) {
11697 if(!IS_FLOAT(operandType( right )))
11698 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11701 unsigned long lit_int;
11705 /* take care if literal is a float */
11706 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11707 lit = info.lit_int;
11710 lit = lit >> (8*offset);
11712 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11713 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11715 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11718 pic16_mov2w(AOP(right), offset);
11719 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11725 pic16_freeAsmop(right,NULL,ic,TRUE);
11730 /*-----------------------------------------------------------------*/
11731 /* genNearPointerSet - pic16_emitcode for near pointer put */
11732 /*-----------------------------------------------------------------*/
11733 static void genNearPointerSet (operand *right,
11739 sym_link *ptype = operandType(result);
11740 sym_link *resetype;
11742 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11743 retype= getSpec(operandType(right));
11744 resetype = getSpec(operandType(result));
11746 pic16_aopOp(result,ic,FALSE);
11748 /* if the result is rematerializable &
11749 * in data space & not a bit variable */
11751 /* and result is not a bit variable */
11752 if (AOP_TYPE(result) == AOP_PCODE
11753 // && AOP_TYPE(result) == AOP_IMMD
11754 && DCL_TYPE(ptype) == POINTER
11755 && !IS_BITFIELD(retype)
11756 && !IS_BITFIELD(resetype)) {
11758 genDataPointerSet (right,result,ic);
11759 pic16_freeAsmop(result,NULL,ic,TRUE);
11763 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11764 pic16_aopOp(right,ic,FALSE);
11765 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11767 /* if the value is already in a pointer register
11768 * then don't need anything more */
11769 if (1 || !AOP_INPREG(AOP(result))) { // AOP_INPREG(AOP(result)) is not always correct...
11770 /* otherwise get a free pointer register */
11771 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11776 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11778 /* if bitfield then unpack the bits */
11779 if (IS_BITFIELD(resetype)) {
11780 genPackBits (resetype, result, right, NULL, POINTER);
11782 /* we have can just get the values */
11783 int size = AOP_SIZE(right);
11786 pic16_loadFSR0(result, 0);
11788 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11790 if (AOP_TYPE(right) == AOP_LIT) {
11791 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11793 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11795 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11797 } else { // no literal
11799 pic16_emitpcode(POC_MOVFF,
11800 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11801 pic16_popCopyReg(&pic16_pc_postinc0)));
11803 pic16_emitpcode(POC_MOVFF,
11804 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11805 pic16_popCopyReg(&pic16_pc_indf0)));
11812 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11813 /* now some housekeeping stuff */
11815 /* we had to allocate for this iCode */
11816 pic16_freeAsmop(NULL,aop,ic,TRUE);
11818 /* we did not allocate which means left
11819 * already in a pointer register, then
11820 * if size > 0 && this could be used again
11821 * we have to point it back to where it
11823 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11824 if (AOP_SIZE(right) > 1
11825 && !OP_SYMBOL(result)->remat
11826 && ( OP_SYMBOL(result)->liveTo > ic->seq
11829 int size = AOP_SIZE(right) - 1;
11832 pic16_emitcode("decf","fsr0,f");
11833 //pic16_emitcode("dec","%s",rname);
11837 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11840 pic16_freeAsmop(right,NULL,ic,TRUE);
11841 pic16_freeAsmop(result,NULL,ic,TRUE);
11844 /*-----------------------------------------------------------------*/
11845 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11846 /*-----------------------------------------------------------------*/
11847 static void genPagedPointerSet (operand *right,
11852 regs *preg = NULL ;
11856 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11858 retype= getSpec(operandType(right));
11860 pic16_aopOp(result,ic,FALSE);
11862 /* if the value is already in a pointer register
11863 then don't need anything more */
11864 if (!AOP_INPREG(AOP(result))) {
11865 /* otherwise get a free pointer register */
11867 preg = getFreePtr(ic,&aop,FALSE);
11868 pic16_emitcode("mov","%s,%s",
11870 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11871 rname = preg->name ;
11873 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11875 pic16_freeAsmop(result,NULL,ic,TRUE);
11876 pic16_aopOp (right,ic,FALSE);
11878 /* if bitfield then unpack the bits */
11879 if (IS_BITFIELD(retype))
11880 genPackBits (retype,result,right,rname,PPOINTER);
11882 /* we have can just get the values */
11883 int size = AOP_SIZE(right);
11887 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11890 pic16_emitcode("movx","@%s,a",rname);
11893 pic16_emitcode("inc","%s",rname);
11899 /* now some housekeeping stuff */
11901 /* we had to allocate for this iCode */
11902 pic16_freeAsmop(NULL,aop,ic,TRUE);
11904 /* we did not allocate which means left
11905 already in a pointer register, then
11906 if size > 0 && this could be used again
11907 we have to point it back to where it
11909 if (AOP_SIZE(right) > 1 &&
11910 !OP_SYMBOL(result)->remat &&
11911 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11913 int size = AOP_SIZE(right) - 1;
11915 pic16_emitcode("dec","%s",rname);
11920 pic16_freeAsmop(right,NULL,ic,TRUE);
11925 /*-----------------------------------------------------------------*/
11926 /* genFarPointerSet - set value from far space */
11927 /*-----------------------------------------------------------------*/
11928 static void genFarPointerSet (operand *right,
11929 operand *result, iCode *ic)
11932 sym_link *retype = getSpec(operandType(right));
11934 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11935 pic16_aopOp(result,ic,FALSE);
11937 /* if the operand is already in dptr
11938 then we do nothing else we move the value to dptr */
11939 if (AOP_TYPE(result) != AOP_STR) {
11940 /* if this is remateriazable */
11941 if (AOP_TYPE(result) == AOP_IMMD)
11942 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11943 else { /* we need to get it byte by byte */
11944 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11945 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11946 if (options.model == MODEL_FLAT24)
11948 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11952 /* so dptr know contains the address */
11953 pic16_freeAsmop(result,NULL,ic,TRUE);
11954 pic16_aopOp(right,ic,FALSE);
11956 /* if bit then unpack */
11957 if (IS_BITFIELD(retype))
11958 genPackBits(retype,result,right,"dptr",FPOINTER);
11960 size = AOP_SIZE(right);
11964 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11966 pic16_emitcode("movx","@dptr,a");
11968 pic16_emitcode("inc","dptr");
11972 pic16_freeAsmop(right,NULL,ic,TRUE);
11975 /*-----------------------------------------------------------------*/
11976 /* genGenPointerSet - set value from generic pointer space */
11977 /*-----------------------------------------------------------------*/
11979 static void genGenPointerSet (operand *right,
11980 operand *result, iCode *ic)
11982 int i, size, offset, lit;
11983 sym_link *retype = getSpec(operandType(right));
11985 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11987 pic16_aopOp(result,ic,FALSE);
11988 pic16_aopOp(right,ic,FALSE);
11989 size = AOP_SIZE(right);
11992 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11994 /* if the operand is already in dptr
11995 then we do nothing else we move the value to dptr */
11996 if (AOP_TYPE(result) != AOP_STR) {
11997 /* if this is remateriazable */
11998 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11999 // WARNING: anythig until "else" is untested!
12000 if (AOP_TYPE(result) == AOP_IMMD) {
12001 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12002 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12003 // load FSR0 from immediate
12004 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12008 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12010 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12016 else { /* we need to get it byte by byte */
12017 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12018 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12020 // set up FSR0 with address of result
12021 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12022 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12024 /* hack hack! see if this the FSR. If so don't load W */
12025 if(AOP_TYPE(right) != AOP_ACC) {
12027 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12029 if(AOP_TYPE(right) == AOP_LIT)
12032 // note: pic16_popGet handles sign extension
12033 for(i=0;i<size;i++) {
12034 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12036 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12038 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12043 for(i=0;i<size;i++) {
12045 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12046 pic16_popCopyReg(&pic16_pc_postinc0)));
12048 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12049 pic16_popCopyReg(&pic16_pc_indf0)));
12055 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12056 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12058 } // if (AOP_TYPE(result) != AOP_IMMD)
12060 } // if (AOP_TYPE(result) != AOP_STR)
12061 /* so dptr know contains the address */
12064 /* if bit then unpack */
12065 if (IS_BITFIELD(retype))
12066 genPackBits(retype,result,right,"dptr",GPOINTER);
12068 size = AOP_SIZE(right);
12071 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12073 // set up FSR0 with address of result
12074 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12075 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12078 if (AOP_TYPE(right) == AOP_LIT) {
12079 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12081 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12083 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12085 } else { // no literal
12087 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12089 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12097 pic16_freeAsmop(right,NULL,ic,TRUE);
12098 pic16_freeAsmop(result,NULL,ic,TRUE);
12102 static void genGenPointerSet (operand *right,
12103 operand *result, iCode *ic)
12106 sym_link *retype = getSpec(operandType(right));
12108 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12110 pic16_aopOp(result,ic,FALSE);
12111 pic16_aopOp(right,ic,FALSE);
12112 size = AOP_SIZE(right);
12114 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12117 /* if bit then unpack */
12118 if (IS_BITFIELD(retype)) {
12119 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12120 genPackBits(retype,result,right,"dptr",GPOINTER);
12124 size = AOP_SIZE(right);
12126 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12130 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12132 /* value of right+0 is placed on stack, which will be retrieved
12133 * by the support function this restoring the stack. The important
12134 * thing is that there is no need to manually restore stack pointer
12136 pushaop(AOP(right), 0);
12137 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12138 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12139 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12140 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12142 /* load address to write to in WREG:FSR0H:FSR0L */
12143 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12144 pic16_popCopyReg(&pic16_pc_fsr0l)));
12145 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12146 pic16_popCopyReg(&pic16_pc_prodl)));
12147 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12149 pic16_callGenericPointerRW(1, size);
12152 pic16_freeAsmop(right,NULL,ic,TRUE);
12153 pic16_freeAsmop(result,NULL,ic,TRUE);
12156 /*-----------------------------------------------------------------*/
12157 /* genPointerSet - stores the value into a pointer location */
12158 /*-----------------------------------------------------------------*/
12159 static void genPointerSet (iCode *ic)
12161 operand *right, *result ;
12162 sym_link *type, *etype;
12167 right = IC_RIGHT(ic);
12168 result = IC_RESULT(ic) ;
12170 /* depending on the type of pointer we need to
12171 move it to the correct pointer register */
12172 type = operandType(result);
12173 etype = getSpec(type);
12174 /* if left is of type of pointer then it is simple */
12175 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12176 p_type = DCL_TYPE(type);
12179 /* we have to go by the storage class */
12180 p_type = PTR_TYPE(SPEC_OCLS(etype));
12182 /* if (SPEC_OCLS(etype)->codesp ) { */
12183 /* p_type = CPOINTER ; */
12186 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12187 /* p_type = FPOINTER ; */
12189 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12190 /* p_type = PPOINTER ; */
12192 /* if (SPEC_OCLS(etype) == idata ) */
12193 /* p_type = IPOINTER ; */
12195 /* p_type = POINTER ; */
12198 /* now that we have the pointer type we assign
12199 the pointer values */
12203 genNearPointerSet (right,result,ic);
12207 genPagedPointerSet (right,result,ic);
12211 genFarPointerSet (right,result,ic);
12215 genGenPointerSet (right,result,ic);
12219 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12220 "genPointerSet: illegal pointer type");
12224 /*-----------------------------------------------------------------*/
12225 /* genIfx - generate code for Ifx statement */
12226 /*-----------------------------------------------------------------*/
12227 static void genIfx (iCode *ic, iCode *popIc)
12229 operand *cond = IC_COND(ic);
12234 pic16_aopOp(cond,ic,FALSE);
12236 /* get the value into acc */
12237 if (AOP_TYPE(cond) != AOP_CRY)
12238 pic16_toBoolean(cond);
12241 /* the result is now in the accumulator */
12242 pic16_freeAsmop(cond,NULL,ic,TRUE);
12244 /* if there was something to be popped then do it */
12248 /* if the condition is a bit variable */
12249 if (isbit && IS_ITEMP(cond) &&
12251 genIfxJump(ic,"c");
12252 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12254 if (isbit && !IS_ITEMP(cond))
12255 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12257 genIfxJump(ic,"a");
12262 /*-----------------------------------------------------------------*/
12263 /* genAddrOf - generates code for address of */
12264 /*-----------------------------------------------------------------*/
12265 static void genAddrOf (iCode *ic)
12267 operand *result, *left;
12269 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12270 pCodeOp *pcop0, *pcop1, *pcop2;
12274 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12276 sym = OP_SYMBOL( IC_LEFT(ic) );
12279 /* get address of symbol on stack */
12280 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12282 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12283 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12286 // operands on stack are accessible via "FSR2 + index" with index
12287 // starting at 2 for arguments and growing from 0 downwards for
12288 // local variables (index == 0 is not assigned so we add one here)
12290 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12292 assert (soffs < 0);
12295 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12296 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12297 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12298 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12299 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12300 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12301 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12307 // if(pic16_debug_verbose) {
12308 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12309 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12312 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12313 size = AOP_SIZE(IC_RESULT(ic));
12315 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12316 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12317 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12320 pic16_emitpcode(POC_MOVLW, pcop0);
12321 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12322 pic16_emitpcode(POC_MOVLW, pcop1);
12323 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12324 pic16_emitpcode(POC_MOVLW, pcop2);
12325 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12328 pic16_emitpcode(POC_MOVLW, pcop0);
12329 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12330 pic16_emitpcode(POC_MOVLW, pcop1);
12331 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12333 pic16_emitpcode(POC_MOVLW, pcop0);
12334 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12337 pic16_freeAsmop(left, NULL, ic, FALSE);
12339 pic16_freeAsmop(result,NULL,ic,TRUE);
12344 /*-----------------------------------------------------------------*/
12345 /* genFarFarAssign - assignment when both are in far space */
12346 /*-----------------------------------------------------------------*/
12347 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12349 int size = AOP_SIZE(right);
12352 /* first push the right side on to the stack */
12354 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12356 pic16_emitcode ("push","acc");
12359 pic16_freeAsmop(right,NULL,ic,FALSE);
12360 /* now assign DPTR to result */
12361 pic16_aopOp(result,ic,FALSE);
12362 size = AOP_SIZE(result);
12364 pic16_emitcode ("pop","acc");
12365 pic16_aopPut(AOP(result),"a",--offset);
12367 pic16_freeAsmop(result,NULL,ic,FALSE);
12372 /*-----------------------------------------------------------------*/
12373 /* genAssign - generate code for assignment */
12374 /*-----------------------------------------------------------------*/
12375 static void genAssign (iCode *ic)
12377 operand *result, *right;
12378 int size, offset,know_W;
12379 unsigned long lit = 0L;
12381 result = IC_RESULT(ic);
12382 right = IC_RIGHT(ic) ;
12386 /* if they are the same */
12387 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12390 /* reversed order operands are aopOp'ed so that result operand
12391 * is effective in case right is a stack symbol. This maneauver
12392 * allows to use the _G.resDirect flag later */
12393 pic16_aopOp(result,ic,TRUE);
12394 pic16_aopOp(right,ic,FALSE);
12396 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12398 /* if they are the same registers */
12399 if (pic16_sameRegs(AOP(right),AOP(result)))
12402 /* if the result is a bit */
12403 if (AOP_TYPE(result) == AOP_CRY) {
12404 /* if the right size is a literal then
12405 we know what the value is */
12406 if (AOP_TYPE(right) == AOP_LIT) {
12408 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12409 pic16_popGet(AOP(result),0));
12411 if (((int) operandLitValue(right)))
12412 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12413 AOP(result)->aopu.aop_dir,
12414 AOP(result)->aopu.aop_dir);
12416 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12417 AOP(result)->aopu.aop_dir,
12418 AOP(result)->aopu.aop_dir);
12422 /* the right is also a bit variable */
12423 if (AOP_TYPE(right) == AOP_CRY) {
12424 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12425 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12426 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12428 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12429 AOP(result)->aopu.aop_dir,
12430 AOP(result)->aopu.aop_dir);
12431 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12432 AOP(right)->aopu.aop_dir,
12433 AOP(right)->aopu.aop_dir);
12434 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12435 AOP(result)->aopu.aop_dir,
12436 AOP(result)->aopu.aop_dir);
12440 /* we need to or */
12441 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12442 pic16_toBoolean(right);
12444 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12445 //pic16_aopPut(AOP(result),"a",0);
12449 /* bit variables done */
12451 size = AOP_SIZE(result);
12454 if(AOP_TYPE(right) == AOP_LIT) {
12455 if(!IS_FLOAT(operandType( right )))
12456 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12459 unsigned long lit_int;
12463 /* take care if literal is a float */
12464 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12465 lit = info.lit_int;
12469 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12470 // sizeof(unsigned long int), sizeof(float));
12473 if (AOP_TYPE(right) == AOP_REG) {
12474 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12477 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12482 if(AOP_TYPE(right) != AOP_LIT
12483 && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))
12484 && !IS_FUNC(OP_SYM_TYPE(right))
12486 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12487 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12489 // set up table pointer
12490 if(is_LitOp(right)) {
12491 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12492 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12493 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12494 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12495 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12496 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12497 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12499 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12500 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12501 pic16_popCopyReg(&pic16_pc_tblptrl)));
12502 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12503 pic16_popCopyReg(&pic16_pc_tblptrh)));
12504 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12505 pic16_popCopyReg(&pic16_pc_tblptru)));
12508 size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
12510 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12511 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12512 pic16_popGet(AOP(result),offset)));
12516 size = getSize(OP_SYM_ETYPE(right));
12517 if(AOP_SIZE(result) > size) {
12518 size = AOP_SIZE(result) - size;
12520 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12530 /* VR - What is this?! */
12531 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12532 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12533 if(aopIdx(AOP(result),0) == 4) {
12535 /* this is a workaround to save value of right into wreg too,
12536 * value of wreg is going to be used later */
12537 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12538 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12539 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12543 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12549 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12550 if(AOP_TYPE(right) == AOP_LIT) {
12552 if(know_W != (lit&0xff))
12553 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12555 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12557 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12561 } else if (AOP_TYPE(right) == AOP_CRY) {
12562 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12564 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12565 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12566 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12568 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12569 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12570 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12572 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12574 if(!_G.resDirect) /* use this aopForSym feature */
12575 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12582 pic16_freeAsmop (right,NULL,ic,FALSE);
12583 pic16_freeAsmop (result,NULL,ic,TRUE);
12586 /*-----------------------------------------------------------------*/
12587 /* genJumpTab - generates code for jump table */
12588 /*-----------------------------------------------------------------*/
12589 static void genJumpTab (iCode *ic)
12594 pCodeOp *jt_offs_hi;
12599 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12600 /* get the condition into accumulator */
12601 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12603 /* multiply by three */
12604 pic16_emitcode("add","a,acc");
12605 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12607 jtab = newiTempLabel(NULL);
12608 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12609 pic16_emitcode("jmp","@a+dptr");
12610 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12613 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12614 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12616 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12617 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12618 pic16_emitpLabel(jtab->key);
12622 jt_offs = pic16_popGetTempReg(0);
12623 jt_offs_hi = pic16_popGetTempReg(1);
12624 jt_label = pic16_popGetLabel (jtab->key);
12625 //fprintf (stderr, "Creating jump table...\n");
12627 // calculate offset into jump table (idx * sizeof (GOTO))
12628 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12629 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12630 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12631 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12632 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12633 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12634 pic16_emitpcode(POC_MOVWF , jt_offs);
12636 // prepare PCLATx (set to first entry in jump table)
12637 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12638 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12639 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12640 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12641 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12643 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12644 pic16_emitpcode(POC_ADDWF , jt_offs);
12645 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12646 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12648 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12650 // release temporaries and prepare jump into table (new PCL --> WREG)
12651 pic16_emitpcode(POC_MOVFW , jt_offs);
12652 pic16_popReleaseTempReg (jt_offs_hi, 1);
12653 pic16_popReleaseTempReg (jt_offs, 0);
12655 // jump into the table
12656 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12658 pic16_emitpLabelFORCE(jtab->key);
12661 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12662 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12664 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12665 /* now generate the jump labels */
12666 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12667 jtab = setNextItem(IC_JTLABELS(ic))) {
12668 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12669 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12672 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12676 /*-----------------------------------------------------------------*/
12677 /* genMixedOperation - gen code for operators between mixed types */
12678 /*-----------------------------------------------------------------*/
12680 TSD - Written for the PIC port - but this unfortunately is buggy.
12681 This routine is good in that it is able to efficiently promote
12682 types to different (larger) sizes. Unfortunately, the temporary
12683 variables that are optimized out by this routine are sometimes
12684 used in other places. So until I know how to really parse the
12685 iCode tree, I'm going to not be using this routine :(.
12687 static int genMixedOperation (iCode *ic)
12690 operand *result = IC_RESULT(ic);
12691 sym_link *ctype = operandType(IC_LEFT(ic));
12692 operand *right = IC_RIGHT(ic);
12698 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12700 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12706 nextright = IC_RIGHT(nextic);
12707 nextleft = IC_LEFT(nextic);
12708 nextresult = IC_RESULT(nextic);
12710 pic16_aopOp(right,ic,FALSE);
12711 pic16_aopOp(result,ic,FALSE);
12712 pic16_aopOp(nextright, nextic, FALSE);
12713 pic16_aopOp(nextleft, nextic, FALSE);
12714 pic16_aopOp(nextresult, nextic, FALSE);
12716 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12718 operand *t = right;
12722 pic16_emitcode(";remove right +","");
12724 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12726 operand *t = right;
12730 pic16_emitcode(";remove left +","");
12734 big = AOP_SIZE(nextleft);
12735 small = AOP_SIZE(nextright);
12737 switch(nextic->op) {
12740 pic16_emitcode(";optimize a +","");
12741 /* if unsigned or not an integral type */
12742 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12743 pic16_emitcode(";add a bit to something","");
12746 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12748 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12749 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12750 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12752 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12760 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12761 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12762 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12765 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12767 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12768 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12769 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12770 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12771 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12774 pic16_emitcode("rlf","known_zero,w");
12781 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12782 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12783 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12785 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12795 pic16_freeAsmop(right,NULL,ic,TRUE);
12796 pic16_freeAsmop(result,NULL,ic,TRUE);
12797 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12798 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12800 nextic->generated = 1;
12807 /*-----------------------------------------------------------------*/
12808 /* genCast - gen code for casting */
12809 /*-----------------------------------------------------------------*/
12810 static void genCast (iCode *ic)
12812 operand *result = IC_RESULT(ic);
12813 sym_link *ctype = operandType(IC_LEFT(ic));
12814 sym_link *rtype = operandType(IC_RIGHT(ic));
12815 sym_link *restype = operandType(IC_RESULT(ic));
12816 operand *right = IC_RIGHT(ic);
12822 /* if they are equivalent then do nothing */
12823 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12826 pic16_aopOp(result,ic,FALSE);
12827 pic16_aopOp(right,ic,FALSE) ;
12829 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12832 /* if the result is a bit */
12833 if (AOP_TYPE(result) == AOP_CRY) {
12835 /* if the right size is a literal then
12836 * we know what the value is */
12837 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12839 if (AOP_TYPE(right) == AOP_LIT) {
12840 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12841 pic16_popGet(AOP(result),0));
12843 if (((int) operandLitValue(right)))
12844 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12845 AOP(result)->aopu.aop_dir,
12846 AOP(result)->aopu.aop_dir);
12848 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12849 AOP(result)->aopu.aop_dir,
12850 AOP(result)->aopu.aop_dir);
12854 /* the right is also a bit variable */
12855 if (AOP_TYPE(right) == AOP_CRY) {
12857 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12859 pic16_emitcode("clrc","");
12860 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12861 AOP(right)->aopu.aop_dir,
12862 AOP(right)->aopu.aop_dir);
12863 pic16_aopPut(AOP(result),"c",0);
12867 /* we need to or */
12868 if (AOP_TYPE(right) == AOP_REG) {
12869 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12870 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12871 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12873 pic16_toBoolean(right);
12874 pic16_aopPut(AOP(result),"a",0);
12878 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12881 size = AOP_SIZE(result);
12883 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12885 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12886 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12887 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12890 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12895 if(IS_BITFIELD(getSpec(restype))
12896 && IS_BITFIELD(getSpec(rtype))) {
12897 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12900 /* if they are the same size : or less */
12901 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12903 /* if they are in the same place */
12904 if (pic16_sameRegs(AOP(right),AOP(result)))
12907 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12909 if (IS_PTR_CONST(rtype))
12911 if (IS_CODEPTR(rtype))
12913 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12916 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12918 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12920 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12923 if(AOP_TYPE(right) == AOP_IMMD) {
12924 pCodeOp *pcop0, *pcop1, *pcop2;
12925 symbol *sym = OP_SYMBOL( right );
12927 size = AOP_SIZE(result);
12929 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12931 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12933 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12936 pic16_emitpcode(POC_MOVLW, pcop0);
12937 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12938 pic16_emitpcode(POC_MOVLW, pcop1);
12939 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12940 pic16_emitpcode(POC_MOVLW, pcop2);
12941 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12944 pic16_emitpcode(POC_MOVLW, pcop0);
12945 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12946 pic16_emitpcode(POC_MOVLW, pcop1);
12947 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12949 pic16_emitpcode(POC_MOVLW, pcop0);
12950 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12954 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12955 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12956 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12957 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12958 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12959 if(AOP_SIZE(result) <2)
12960 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12962 /* if they in different places then copy */
12963 size = AOP_SIZE(result);
12966 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12967 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12974 /* if the result is of type pointer */
12975 if (IS_PTR(ctype)) {
12977 sym_link *type = operandType(right);
12978 sym_link *etype = getSpec(type);
12980 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12982 /* pointer to generic pointer */
12983 if (IS_GENPTR(ctype)) {
12987 p_type = DCL_TYPE(type);
12989 /* we have to go by the storage class */
12990 p_type = PTR_TYPE(SPEC_OCLS(etype));
12992 /* if (SPEC_OCLS(etype)->codesp ) */
12993 /* p_type = CPOINTER ; */
12995 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12996 /* p_type = FPOINTER ; */
12998 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12999 /* p_type = PPOINTER; */
13001 /* if (SPEC_OCLS(etype) == idata ) */
13002 /* p_type = IPOINTER ; */
13004 /* p_type = POINTER ; */
13007 /* the first two bytes are known */
13008 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
13009 size = GPTRSIZE - 1;
13012 if(offset < AOP_SIZE(right)) {
13013 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13014 pic16_mov2f(AOP(result), AOP(right), offset);
13016 if ((AOP_TYPE(right) == AOP_PCODE) &&
13017 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13018 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13019 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13022 pic16_aopPut(AOP(result),
13023 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13028 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13031 /* the last byte depending on type */
13035 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13036 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13037 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
13041 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13045 pic16_emitcode(";BUG!? ","%d",__LINE__);
13049 pic16_emitcode(";BUG!? ","%d",__LINE__);
13054 if (GPTRSIZE > AOP_SIZE(right)) {
13055 // assume data pointer... THIS MIGHT BE WRONG!
13056 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13057 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13059 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13064 /* this should never happen */
13065 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13066 "got unknown pointer type");
13069 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13075 /* just copy the pointers */
13076 size = AOP_SIZE(result);
13079 pic16_aopPut(AOP(result),
13080 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13089 /* so we now know that the size of destination is greater
13090 than the size of the source.
13091 Now, if the next iCode is an operator then we might be
13092 able to optimize the operation without performing a cast.
13094 if(genMixedOperation(ic))
13097 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13099 /* we move to result for the size of source */
13100 size = AOP_SIZE(right);
13105 pic16_mov2f(AOP(result), AOP(right), offset);
13109 /* now depending on the sign of the destination */
13110 size = AOP_SIZE(result) - AOP_SIZE(right);
13111 /* if unsigned or not an integral type */
13112 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13114 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13116 /* we need to extend the sign :( */
13119 /* Save one instruction of casting char to int */
13120 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13121 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13122 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13124 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13127 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13129 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13131 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13134 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13139 pic16_freeAsmop(right,NULL,ic,TRUE);
13140 pic16_freeAsmop(result,NULL,ic,TRUE);
13144 /*-----------------------------------------------------------------*/
13145 /* genDjnz - generate decrement & jump if not zero instrucion */
13146 /*-----------------------------------------------------------------*/
13147 static int genDjnz (iCode *ic, iCode *ifx)
13149 symbol *lbl, *lbl1;
13150 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13155 /* if the if condition has a false label
13156 then we cannot save */
13160 /* if the minus is not of the form
13162 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13163 !IS_OP_LITERAL(IC_RIGHT(ic)))
13166 if (operandLitValue(IC_RIGHT(ic)) != 1)
13169 /* if the size of this greater than one then no
13171 if (getSize(operandType(IC_RESULT(ic))) > 1)
13174 /* otherwise we can save BIG */
13175 lbl = newiTempLabel(NULL);
13176 lbl1= newiTempLabel(NULL);
13178 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13180 if (IS_AOP_PREG(IC_RESULT(ic))) {
13181 pic16_emitcode("dec","%s",
13182 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13183 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13184 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13188 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13189 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13191 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13192 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13196 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13197 ifx->generated = 1;
13201 /*-----------------------------------------------------------------*/
13202 /* genReceive - generate code for a receive iCode */
13203 /*-----------------------------------------------------------------*/
13204 static void genReceive (iCode *ic)
13210 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13211 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13213 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13215 if (isOperandInFarSpace(IC_RESULT(ic))
13216 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13217 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13219 int size = getSize(operandType(IC_RESULT(ic)));
13220 int offset = pic16_fReturnSizePic - size;
13224 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13225 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13229 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13231 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13232 size = AOP_SIZE(IC_RESULT(ic));
13235 pic16_emitcode ("pop","acc");
13236 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13239 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13241 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13244 /* set pseudo stack pointer to where it should be - dw*/
13245 GpsuedoStkPtr = ic->parmBytes;
13247 /* setting GpsuedoStkPtr has side effects here: */
13248 assignResultValue(IC_RESULT(ic), 0);
13251 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13254 /*-----------------------------------------------------------------*/
13255 /* genDummyRead - generate code for dummy read of volatiles */
13256 /*-----------------------------------------------------------------*/
13258 genDummyRead (iCode * ic)
13264 if (op && IS_SYMOP(op)) {
13265 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13266 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13269 pic16_aopOp (op, ic, FALSE);
13270 for (i=0; i < AOP_SIZE(op); i++) {
13271 // may need to protect this from the peepholer -- this is not nice but works...
13272 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13273 pic16_mov2w (AOP(op),i);
13274 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13276 pic16_freeAsmop (op, NULL, ic, TRUE);
13278 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13282 /*-----------------------------------------------------------------*/
13283 /* genpic16Code - generate code for pic16 based controllers */
13284 /*-----------------------------------------------------------------*/
13286 * At this point, ralloc.c has gone through the iCode and attempted
13287 * to optimize in a way suitable for a PIC. Now we've got to generate
13288 * PIC instructions that correspond to the iCode.
13290 * Once the instructions are generated, we'll pass through both the
13291 * peep hole optimizer and the pCode optimizer.
13292 *-----------------------------------------------------------------*/
13294 void genpic16Code (iCode *lic)
13299 lineHead = lineCurr = NULL;
13301 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13302 pic16_addpBlock(pb);
13305 /* if debug information required */
13306 if (options.debug && currFunc) {
13308 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13313 for (ic = lic ; ic ; ic = ic->next ) {
13315 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13316 if ( cln != ic->lineno ) {
13317 if ( options.debug ) {
13318 debugFile->writeCLine (ic);
13321 if(!options.noCcodeInAsm) {
13322 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13323 printCLine(ic->filename, ic->lineno)));
13329 if(options.iCodeInAsm) {
13332 /* insert here code to print iCode as comment */
13333 l = Safe_strdup(printILine(ic));
13334 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13337 /* if the result is marked as
13338 * spilt and rematerializable or code for
13339 * this has already been generated then
13341 if (resultRemat(ic) || ic->generated )
13344 /* depending on the operation */
13363 /* IPOP happens only when trying to restore a
13364 * spilt live range, if there is an ifx statement
13365 * following this pop then the if statement might
13366 * be using some of the registers being popped which
13367 * would destroy the contents of the register so
13368 * we need to check for this condition and handle it */
13370 && ic->next->op == IFX
13371 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13372 genIfx (ic->next,ic);
13390 genEndFunction (ic);
13406 pic16_genPlus (ic) ;
13410 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13411 pic16_genMinus (ic);
13427 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13431 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13437 /* note these two are xlated by algebraic equivalence
13438 * during parsing SDCC.y */
13439 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13440 "got '>=' or '<=' shouldn't have come here");
13444 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13456 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13460 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13464 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13488 genRightShift (ic);
13491 case GET_VALUE_AT_ADDRESS:
13496 if (POINTER_SET(ic))
13523 addSet(&_G.sendSet,ic);
13526 case DUMMY_READ_VOLATILE:
13536 /* now we are ready to call the
13537 peep hole optimizer */
13538 if (!options.nopeep)
13539 peepHole (&lineHead);
13541 /* now do the actual printing */
13542 printLine (lineHead, codeOutFile);
13545 DFPRINTF((stderr,"printing pBlock\n\n"));
13546 pic16_printpBlock(stdout,pb);