1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic16
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002)
9 - Vangelis Rokas vrokas@otenet.gr (2003,2004,2005)
10 Bug Fixes - Raphael Neider rneider@web.de (2004,2005)
12 This program is free software; you can redistribute it and/or modify it
13 under the terms of the GNU General Public License as published by the
14 Free Software Foundation; either version 2, or (at your option) any
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 In other words, you are welcome to use, share and improve this program.
27 You are forbidden to forbid anyone else to use, share and improve
28 what you give them. Help stamp out software-hoarding!
31 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
32 Made everything static
33 -------------------------------------------------------------------------*/
39 #include "SDCCglobl.h"
43 #include "SDCCpeeph.h"
51 /* Set the following to 1 to enable the slower/bigger
52 * but more robust generic shifting routine (which also
53 * operates correctly with negative shift values). */
54 #define USE_GENERIC_SIGNED_SHIFT 1
56 /* Set the following to 1 to enable the new
57 * stripped down genCmp version.
58 * This version should be easier to understand,
59 * more reliable and (sigh) slighly slower. */
60 #define USE_SIMPLE_GENCMP 1
62 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
64 void pic16_genMult8X8_8 (operand *, operand *,operand *);
65 void pic16_genMult16X16_16(operand *, operand *, operand *);
66 void pic16_genMult32X32_32(operand *, operand *, operand *);
67 pCode *pic16_AssembleLine(char *line, int peeps);
68 extern void pic16_printpBlock(FILE *of, pBlock *pb);
69 static asmop *newAsmop (short type);
70 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
71 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
72 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
73 static pCodeOp *pic16_popRegFromIdx(int rIdx);
75 //static int aopIdx (asmop *aop, int offset);
77 int pic16_labelOffset=0;
78 extern int pic16_debug_verbose;
79 #if !(USE_GENERIC_SIGNED_SHIFT)
80 static int optimized_for_speed = 0;
89 /* max_key keeps track of the largest label number used in
90 a function. This is then used to adjust the label offset
91 for the next function.
94 static int GpsuedoStkPtr=0;
96 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
98 unsigned int pic16aopLiteral (value *val, int offset);
99 const char *pic16_AopType(short type);
100 static iCode *ifxForOp ( operand *op, iCode *ic );
102 void pic16_pushpCodeOp(pCodeOp *pcop);
103 void pic16_poppCodeOp(pCodeOp *pcop);
105 static bool is_LitOp(operand *op);
106 static bool is_LitAOp(asmop *aop);
109 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
111 /* set the following macro to 1 to enable passing the
112 * first byte of functions parameters via WREG */
113 #define USE_WREG_IN_FUNC_PARAMS 0
116 /* this is the down and dirty file with all kinds of
117 kludgy & hacky stuff. This is what it is all about
118 CODE GENERATION for a specific MCU . some of the
119 routines may be reusable, will have to see */
121 static char *zero = "#0x00";
122 static char *one = "#0x01";
123 //static char *spname = "sp";
127 * Function return value policy (MSB-->LSB):
129 * 16 bits -> PRODL:WREG
130 * 24 bits -> PRODH:PRODL:WREG
131 * 32 bits -> FSR0L:PRODH:PRODL:WREG
132 * >32 bits -> on stack, and FSR0 points to the beginning
137 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
138 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
139 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
140 static char **fReturn = fReturnpic16;
142 static char *accUse[] = {"WREG"};
144 //static short rbank = -1;
158 bitVect *fregsUsed; /* registers used in function */
160 set *sregsAllocSet; /* registers used to store stack variables */
161 int stack_lat; /* stack offset latency */
163 int useWreg; /* flag when WREG is used to pass function parameter */
166 extern int pic16_ptrRegReq ;
167 extern int pic16_nRegs;
168 extern FILE *codeOutFile;
169 //static void saverbank (int, iCode *,bool);
171 static lineNode *lineHead = NULL;
172 static lineNode *lineCurr = NULL;
174 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
175 0xE0, 0xC0, 0x80, 0x00};
176 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
177 0x07, 0x03, 0x01, 0x00};
181 /*-----------------------------------------------------------------*/
182 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
183 /* exponent of 2 is returned, otherwise -1 is */
185 /* note that this is similar to the function `powof2' in SDCCsymt */
189 /*-----------------------------------------------------------------*/
190 int pic16_my_powof2 (unsigned long num)
193 if( (num & (num-1)) == 0) {
206 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
208 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
210 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
211 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
212 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
213 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
214 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
215 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
216 ((result) ? AOP_SIZE(result) : 0));
219 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
222 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
224 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
225 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
226 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
227 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
228 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
229 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
233 void pic16_emitpcomment (char *fmt, ...)
236 char lb[INITIAL_INLINEASM];
237 unsigned char *lbp = lb;
242 vsprintf(lb+1,fmt,ap);
244 while (isspace(*lbp)) lbp++;
247 lineCurr = (lineCurr ?
248 connectLine(lineCurr,newLineNode(lb)) :
249 (lineHead = newLineNode(lb)));
250 lineCurr->isInline = _G.inLine;
251 lineCurr->isDebug = _G.debugLine;
253 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
256 // fprintf(stderr, "%s\n", lb);
259 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
262 char lb[INITIAL_INLINEASM];
263 unsigned char *lbp = lb;
265 if(!pic16_debug_verbose)
272 sprintf(lb,"%s\t",inst);
274 sprintf(lb,"%s",inst);
275 vsprintf(lb+(strlen(lb)),fmt,ap);
279 while (isspace(*lbp)) lbp++;
282 lineCurr = (lineCurr ?
283 connectLine(lineCurr,newLineNode(lb)) :
284 (lineHead = newLineNode(lb)));
285 lineCurr->isInline = _G.inLine;
286 lineCurr->isDebug = _G.debugLine;
288 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
291 // fprintf(stderr, "%s\n", lb);
296 void pic16_emitpLabel(int key)
298 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
301 void pic16_emitpLabelFORCE(int key)
303 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
306 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
307 * NEVER call pic16_emitpcode_real directly, please... */
308 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
312 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
314 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
317 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
320 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
322 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
325 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
328 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
334 #define pic16_emitcode DEBUGpic16_emitcode
336 /*-----------------------------------------------------------------*/
337 /* pic16_emitcode - writes the code into a file : for now it is simple */
338 /*-----------------------------------------------------------------*/
339 void pic16_emitcode (char *inst,char *fmt, ...)
342 char lb[INITIAL_INLINEASM];
343 unsigned char *lbp = lb;
349 sprintf(lb,"%s\t",inst);
351 sprintf(lb,"%s",inst);
352 vsprintf(lb+(strlen(lb)),fmt,ap);
356 while (isspace(*lbp)) lbp++;
359 lineCurr = (lineCurr ?
360 connectLine(lineCurr,newLineNode(lb)) :
361 (lineHead = newLineNode(lb)));
362 lineCurr->isInline = _G.inLine;
363 lineCurr->isDebug = _G.debugLine;
365 // VR fprintf(stderr, "lb = <%s>\n", lbp);
367 // if(pic16_debug_verbose)
368 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
375 /*-----------------------------------------------------------------*/
376 /* pic16_emitDebuggerSymbol - associate the current code location */
377 /* with a debugger symbol */
378 /*-----------------------------------------------------------------*/
380 pic16_emitDebuggerSymbol (char * debugSym)
383 pic16_emitcode (";", "%s ==.", debugSym);
388 /*-----------------------------------------------------------------*/
389 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
390 /*-----------------------------------------------------------------*/
391 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
393 // bool r0iu = FALSE , r1iu = FALSE;
394 // bool r0ou = FALSE , r1ou = FALSE;
395 bool fsr0iu = FALSE, fsr0ou;
396 bool fsr2iu = FALSE, fsr2ou;
398 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
401 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
402 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
404 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
405 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
407 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
408 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
409 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
412 if(!fsr0iu && !fsr0ou) {
413 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
414 (*aopp)->type = AOP_FSR0;
416 fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
418 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
422 /* no usage of FSR2 */
423 if(!fsr2iu && !fsr2ou) {
424 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
425 (*aopp)->type = AOP_FSR2;
427 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
431 /* now we know they both have usage */
432 /* if fsr0 not used in this instruction */
434 if (!_G.fsr0Pushed) {
435 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
436 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
440 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
441 (*aopp)->type = AOP_FSR0;
443 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
445 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
449 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
454 /* the logic: if r0 & r1 used in the instruction
455 then we are in trouble otherwise */
457 /* first check if r0 & r1 are used by this
458 instruction, in which case we are in trouble */
459 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
460 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
465 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
466 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
468 /* if no usage of r0 then return it */
469 if (!r0iu && !r0ou) {
470 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
471 (*aopp)->type = AOP_R0;
473 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
476 /* if no usage of r1 then return it */
477 if (!r1iu && !r1ou) {
478 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
479 (*aopp)->type = AOP_R1;
481 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
484 /* now we know they both have usage */
485 /* if r0 not used in this instruction */
487 /* push it if not already pushed */
489 //pic16_emitcode ("push","%s",
490 // pic16_regWithIdx(R0_IDX)->dname);
494 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
495 (*aopp)->type = AOP_R0;
497 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
500 /* if r1 not used then */
503 /* push it if not already pushed */
505 //pic16_emitcode ("push","%s",
506 // pic16_regWithIdx(R1_IDX)->dname);
510 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
511 (*aopp)->type = AOP_R1;
512 return pic16_regWithIdx(R1_IDX);
516 /* I said end of world but not quite end of world yet */
517 /* if this is a result then we can push it on the stack*/
519 (*aopp)->type = AOP_STK;
523 /* other wise this is true end of the world */
524 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
525 "getFreePtr should never reach here");
530 /*-----------------------------------------------------------------*/
531 /* newAsmop - creates a new asmOp */
532 /*-----------------------------------------------------------------*/
533 static asmop *newAsmop (short type)
537 aop = Safe_calloc(1,sizeof(asmop));
542 static void genSetDPTR(int n)
546 pic16_emitcode(";", "Select standard DPTR");
547 pic16_emitcode("mov", "dps, #0x00");
551 pic16_emitcode(";", "Select alternate DPTR");
552 pic16_emitcode("mov", "dps, #0x01");
556 /*-----------------------------------------------------------------*/
557 /* resolveIfx - converts an iCode ifx into a form more useful for */
558 /* generating code */
559 /*-----------------------------------------------------------------*/
560 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
564 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
570 resIfx->condition = 1; /* assume that the ifx is true */
571 resIfx->generated = 0; /* indicate that the ifx has not been used */
574 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
577 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
578 __FUNCTION__,__LINE__,resIfx->lbl->key);
583 resIfx->lbl = IC_TRUE(ifx);
585 resIfx->lbl = IC_FALSE(ifx);
586 resIfx->condition = 0;
591 DEBUGpic16_emitcode("; +++","ifx true is non-null");
593 DEBUGpic16_emitcode("; +++","ifx true is null");
595 DEBUGpic16_emitcode("; +++","ifx false is non-null");
597 DEBUGpic16_emitcode("; +++","ifx false is null");
601 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
605 /*-----------------------------------------------------------------*/
606 /* pointerCode - returns the code for a pointer type */
607 /*-----------------------------------------------------------------*/
608 static int pointerCode (sym_link *etype)
611 return PTR_TYPE(SPEC_OCLS(etype));
616 /*-----------------------------------------------------------------*/
617 /* aopForSym - for a true symbol */
618 /*-----------------------------------------------------------------*/
619 static asmop *aopForSym (iCode *ic, operand *op, bool result)
621 symbol *sym=OP_SYMBOL(op);
623 memmap *space= SPEC_OCLS(sym->etype);
627 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
629 // sym = OP_SYMBOL(op);
631 /* if already has one */
633 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
638 /* if symbol was initially placed onStack then we must re-place it
639 * to direct memory, since pic16 does not have a specific stack */
641 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
649 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
651 sym->aop = aop = newAsmop (AOP_PAGED);
652 aop->aopu.aop_dir = sym->rname ;
653 aop->size = getSize(sym->type);
654 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
655 pic16_allocDirReg( IC_LEFT(ic) );
663 /* assign depending on the storage class */
664 /* if it is on the stack or indirectly addressable */
665 /* space we need to assign either r0 or r1 to it */
666 if (sym->onStack) // || sym->iaccess)
671 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
672 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
674 /* acquire a temporary register -- it is saved in function */
676 sym->aop = aop = newAsmop(AOP_STA);
677 aop->aopu.stk.stk = sym->stack;
678 aop->size = getSize(sym->type);
681 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
682 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
683 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
684 // pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
686 for(i=0;i<aop->size;i++)
687 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
688 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
690 if(1 && ic->op == SEND) {
692 /* if SEND do the send here */
695 for(i=0;i<aop->size;i++) {
696 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
697 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
702 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
705 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
707 // we do not need to load the value if it is to be defined...
708 if (result) return aop;
711 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
714 for(i=0;i<aop->size;i++) {
716 /* initialise for stack access via frame pointer */
717 // operands on stack are accessible via "FSR2 + index" with index
718 // starting at 2 for arguments and growing from 0 downwards for
719 // local variables (index == 0 is not assigned so we add one here)
721 int soffs = sym->stack;
727 if(1 && ic->op == SEND) {
728 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
729 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
730 pic16_popCopyReg( pic16_frame_plusw ),
731 pic16_popCopyReg(pic16_stack_postdec )));
733 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
734 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
735 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
741 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
748 /* now assign the address of the variable to
749 the pointer register */
750 if (aop->type != AOP_STK) {
754 pic16_emitcode("push","acc");
756 pic16_emitcode("mov","a,_bp");
757 pic16_emitcode("add","a,#0x%02x",
759 ((char)(sym->stack - _G.nRegsSaved )) :
760 ((char)sym->stack)) & 0xff);
761 pic16_emitcode("mov","%s,a",
762 aop->aopu.aop_ptr->name);
765 pic16_emitcode("pop","acc");
767 pic16_emitcode("mov","%s,#%s",
768 aop->aopu.aop_ptr->name,
770 aop->paged = space->paged;
772 aop->aopu.aop_stk = sym->stack;
780 if (sym->onStack && options.stack10bit)
782 /* It's on the 10 bit stack, which is located in
786 //DEBUGpic16_emitcode(";","%d",__LINE__);
789 pic16_emitcode("push","acc");
791 pic16_emitcode("mov","a,_bp");
792 pic16_emitcode("add","a,#0x%02x",
794 ((char)(sym->stack - _G.nRegsSaved )) :
795 ((char)sym->stack)) & 0xff);
798 pic16_emitcode ("mov","dpx1,#0x40");
799 pic16_emitcode ("mov","dph1,#0x00");
800 pic16_emitcode ("mov","dpl1, a");
804 pic16_emitcode("pop","acc");
806 sym->aop = aop = newAsmop(AOP_DPTR2);
807 aop->size = getSize(sym->type);
813 /* special case for a function */
814 if (IS_FUNC(sym->type)) {
815 sym->aop = aop = newAsmop(AOP_PCODE);
816 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
817 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
818 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
819 PCOI(aop->aopu.pcop)->index = 0;
820 aop->size = FPTRSIZE;
821 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
828 //DEBUGpic16_emitcode(";","%d",__LINE__);
829 /* if in bit space */
830 if (IN_BITSPACE(space)) {
831 sym->aop = aop = newAsmop (AOP_CRY);
832 aop->aopu.aop_dir = sym->rname ;
833 aop->size = getSize(sym->type);
834 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
837 /* if it is in direct space */
838 if (IN_DIRSPACE(space)) {
839 sym->aop = aop = newAsmop (AOP_DIR);
840 aop->aopu.aop_dir = sym->rname ;
841 aop->size = getSize(sym->type);
842 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
843 pic16_allocDirReg( IC_LEFT(ic) );
848 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
849 sym->aop = aop = newAsmop (AOP_DIR);
850 aop->aopu.aop_dir = sym->rname ;
851 aop->size = getSize(sym->type);
852 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
853 pic16_allocDirReg( IC_LEFT(ic) );
858 /* only remaining is far space */
859 sym->aop = aop = newAsmop(AOP_PCODE);
861 /* change the next if to 1 to revert to good old immediate code */
862 if(IN_CODESPACE(space)) {
863 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
864 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
865 PCOI(aop->aopu.pcop)->index = 0;
867 /* try to allocate via direct register */
868 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
869 // aop->size = getSize( sym->type );
872 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
873 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
876 if(!pic16_allocDirReg (IC_LEFT(ic)))
880 if(IN_DIRSPACE( space ))
882 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
883 aop->size = FPTRSIZE;
884 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
885 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
886 else if(sym->onStack) {
889 if(SPEC_SCLS(sym->etype) == S_PDATA) {
890 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
891 aop->size = FPTRSIZE;
896 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
898 /* if it is in code space */
899 if (IN_CODESPACE(space))
905 /*-----------------------------------------------------------------*/
906 /* aopForRemat - rematerialzes an object */
907 /*-----------------------------------------------------------------*/
908 static asmop *aopForRemat (operand *op) // x symbol *sym)
910 symbol *sym = OP_SYMBOL(op);
912 iCode *ic = NULL, *oldic;
913 asmop *aop = newAsmop(AOP_PCODE);
920 ic = sym->rematiCode;
922 if(IS_OP_POINTER(op)) {
923 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
929 // pic16_emitpcomment("ic: %s\n", printILine(ic));
932 val += (int) operandLitValue(IC_RIGHT(ic));
933 } else if (ic->op == '-') {
934 val -= (int) operandLitValue(IC_RIGHT(ic));
938 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
941 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
944 if(!op->isaddr)viaimmd++; else viaimmd=0;
946 /* set the following if to 1 to revert to good old immediate code */
947 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
950 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
952 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
955 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
957 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
960 PCOI(aop->aopu.pcop)->index = val;
962 aop->size = getSize( sym->type );
964 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
966 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
967 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
969 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
973 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
974 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
976 val, IS_PTR_CONST(operandType(op)));
978 val, IS_CODEPTR(operandType(op)));
981 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
983 pic16_allocDirReg (IC_LEFT(ic));
985 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
992 static int aopIdx (asmop *aop, int offset)
997 if(aop->type != AOP_REG)
1000 return aop->aopu.aop_reg[offset]->rIdx;
1005 /*-----------------------------------------------------------------*/
1006 /* regsInCommon - two operands have some registers in common */
1007 /*-----------------------------------------------------------------*/
1008 static bool regsInCommon (operand *op1, operand *op2)
1010 symbol *sym1, *sym2;
1013 /* if they have registers in common */
1014 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1017 sym1 = OP_SYMBOL(op1);
1018 sym2 = OP_SYMBOL(op2);
1020 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1023 for (i = 0 ; i < sym1->nRegs ; i++) {
1028 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1032 if (sym2->regs[j] == sym1->regs[i])
1040 /*-----------------------------------------------------------------*/
1041 /* operandsEqu - equivalent */
1042 /*-----------------------------------------------------------------*/
1043 static bool operandsEqu ( operand *op1, operand *op2)
1045 symbol *sym1, *sym2;
1047 /* if they not symbols */
1048 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1051 sym1 = OP_SYMBOL(op1);
1052 sym2 = OP_SYMBOL(op2);
1054 /* if both are itemps & one is spilt
1055 and the other is not then false */
1056 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1057 sym1->isspilt != sym2->isspilt )
1060 /* if they are the same */
1064 if (sym1->rname[0] && sym2->rname[0]
1065 && strcmp (sym1->rname, sym2->rname) == 0)
1069 /* if left is a tmp & right is not */
1070 if (IS_ITEMP(op1) &&
1073 (sym1->usl.spillLoc == sym2))
1076 if (IS_ITEMP(op2) &&
1080 (sym2->usl.spillLoc == sym1))
1086 /*-----------------------------------------------------------------*/
1087 /* pic16_sameRegs - two asmops have the same registers */
1088 /*-----------------------------------------------------------------*/
1089 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1096 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1097 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1099 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1101 if (aop1->type != AOP_REG ||
1102 aop2->type != AOP_REG )
1105 /* This is a bit too restrictive if one is a subset of the other...
1106 if (aop1->size != aop2->size )
1110 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1111 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1113 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1114 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1121 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1123 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1124 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1126 if(aop1 == aop2)return TRUE;
1127 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1129 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1135 /*-----------------------------------------------------------------*/
1136 /* pic16_aopOp - allocates an asmop for an operand : */
1137 /*-----------------------------------------------------------------*/
1138 void pic16_aopOp (operand *op, iCode *ic, bool result)
1147 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1149 /* if this a literal */
1150 if (IS_OP_LITERAL(op)) {
1151 op->aop = aop = newAsmop(AOP_LIT);
1152 aop->aopu.aop_lit = op->operand.valOperand;
1153 aop->size = getSize(operandType(op));
1158 sym_link *type = operandType(op);
1160 if(IS_PTR_CONST(type))
1162 if(IS_CODEPTR(type))
1164 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1167 /* if already has a asmop then continue */
1171 /* if the underlying symbol has a aop */
1172 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1173 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1174 op->aop = OP_SYMBOL(op)->aop;
1178 /* if this is a true symbol */
1179 if (IS_TRUE_SYMOP(op)) {
1180 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1181 op->aop = aopForSym(ic, op, result);
1185 /* this is a temporary : this has
1191 e) can be a return use only */
1193 sym = OP_SYMBOL(op);
1195 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1196 /* if the type is a conditional */
1197 if (sym->regType == REG_CND) {
1198 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1203 /* if it is spilt then two situations
1205 b) has a spill location */
1206 if (sym->isspilt || sym->nRegs == 0) {
1208 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1209 DEBUGpic16_emitcode(";","%d",__LINE__);
1210 /* rematerialize it NOW */
1213 sym->aop = op->aop = aop = aopForRemat (op);
1214 // aop->size = getSize(sym->type);
1215 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1222 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1223 aop->size = getSize(sym->type);
1224 for ( i = 0 ; i < 1 ; i++ ) {
1225 aop->aopu.aop_str[i] = accUse[i];
1226 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1228 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1229 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1237 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1238 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1239 //pic16_allocDirReg (IC_LEFT(ic));
1240 aop->size = getSize(sym->type);
1245 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1246 aop->size = getSize(sym->type);
1247 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1248 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1250 DEBUGpic16_emitcode(";","%d",__LINE__);
1254 /* else spill location */
1255 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1256 /* force a new aop if sizes differ */
1257 sym->usl.spillLoc->aop = NULL;
1261 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1262 __FUNCTION__,__LINE__,
1263 sym->usl.spillLoc->rname,
1264 sym->rname, sym->usl.spillLoc->offset);
1267 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1268 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1269 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1270 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1272 sym->usl.spillLoc->offset, op);
1274 fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1275 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1276 assert (getSize(sym->type) <= 1);
1277 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1279 aop->size = getSize(sym->type);
1285 sym_link *type = operandType(op);
1287 if(IS_PTR_CONST(type))
1289 if(IS_CODEPTR(type))
1291 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1294 /* must be in a register */
1295 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1296 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1297 aop->size = sym->nRegs;
1298 for ( i = 0 ; i < sym->nRegs ;i++)
1299 aop->aopu.aop_reg[i] = sym->regs[i];
1302 /*-----------------------------------------------------------------*/
1303 /* pic16_freeAsmop - free up the asmop given to an operand */
1304 /*----------------------------------------------------------------*/
1305 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1322 /* depending on the asmop type only three cases need work AOP_RO
1323 , AOP_R1 && AOP_STK */
1325 switch (aop->type) {
1327 if (_G.fsr0Pushed ) {
1329 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1330 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1331 // pic16_emitcode ("pop","ar0");
1335 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1339 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1345 pic16_emitcode ("pop","ar0");
1349 bitVectUnSetBit(ic->rUsed,R0_IDX);
1355 pic16_emitcode ("pop","ar1");
1359 bitVectUnSetBit(ic->rUsed,R1_IDX);
1366 /* we must store the result on stack */
1367 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1368 // operands on stack are accessible via "FSR2 + index" with index
1369 // starting at 2 for arguments and growing from 0 downwards for
1370 // local variables (index == 0 is not assigned so we add one here)
1371 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1376 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1377 for(i=0;i<aop->size;i++) {
1378 /* initialise for stack access via frame pointer */
1379 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1380 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1381 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1384 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1388 for(i=0;i<aop->size;i++) {
1389 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1391 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1392 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1403 int stk = aop->aopu.aop_stk + aop->size;
1404 bitVectUnSetBit(ic->rUsed,R0_IDX);
1405 bitVectUnSetBit(ic->rUsed,R1_IDX);
1407 getFreePtr(ic,&aop,FALSE);
1409 if (options.stack10bit)
1411 /* I'm not sure what to do here yet... */
1414 "*** Warning: probably generating bad code for "
1415 "10 bit stack mode.\n");
1419 pic16_emitcode ("mov","a,_bp");
1420 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1421 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1423 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1427 pic16_emitcode("pop","acc");
1428 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1430 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1433 pic16_freeAsmop(op,NULL,ic,TRUE);
1435 pic16_emitcode("pop","ar0");
1440 pic16_emitcode("pop","ar1");
1450 /* all other cases just dealloc */
1454 OP_SYMBOL(op)->aop = NULL;
1455 /* if the symbol has a spill */
1457 SPIL_LOC(op)->aop = NULL;
1462 /*-----------------------------------------------------------------*/
1463 /* pic16_aopGet - for fetching value of the aop */
1464 /*-----------------------------------------------------------------*/
1465 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1470 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1472 /* offset is greater than size then zero */
1473 if (offset > (aop->size - 1) &&
1474 aop->type != AOP_LIT)
1477 /* depending on type */
1478 switch (aop->type) {
1482 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1483 rs = Safe_calloc(1, strlen(s)+1);
1488 /* if we need to increment it */
1489 while (offset > aop->coff)
1491 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1495 while (offset < aop->coff)
1497 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1503 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1504 return (dname ? "acc" : "a");
1506 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1507 rs = Safe_calloc (1, strlen (s) + 1);
1515 sprintf (s,"%s",aop->aopu.aop_immd);
1518 sprintf(s,"(%s >> %d)",
1523 aop->aopu.aop_immd);
1524 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1525 rs = Safe_calloc(1,strlen(s)+1);
1531 sprintf(s,"(%s + %d)",
1534 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1536 sprintf(s,"%s",aop->aopu.aop_dir);
1537 rs = Safe_calloc(1,strlen(s)+1);
1543 // return aop->aopu.aop_reg[offset]->dname;
1545 return aop->aopu.aop_reg[offset]->name;
1548 //pic16_emitcode(";","%d",__LINE__);
1549 return aop->aopu.aop_dir;
1552 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1553 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1555 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1556 rs = Safe_strdup("WREG");
1560 sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1561 rs = Safe_calloc(1,strlen(s)+1);
1566 aop->coff = offset ;
1568 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1571 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1572 aop->type = AOP_ACC;
1573 return Safe_strdup("WREG");
1575 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1577 return aop->aopu.aop_str[offset];
1581 pCodeOp *pcop = aop->aopu.pcop;
1582 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1584 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1585 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1587 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1589 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1592 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1595 rs = Safe_calloc(1,strlen(s)+1);
1601 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1603 sprintf(s,"(%s + %d)",
1607 sprintf(s,"%s",aop->aopu.aop_dir);
1608 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1609 rs = Safe_calloc(1,strlen(s)+1);
1615 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1619 // pCodeOp *pcop = aop->aop
1624 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1625 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1626 "aopget got unsupported aop->type");
1632 /* lock has the following meaning: When allocating temporary registers
1633 * for stack variables storage, the value of the temporary register is
1634 * saved on stack. Its value is restored at the end. This procedure is
1635 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1636 * a possibility that before a call to pic16_aopOp, a temporary register
1637 * is allocated for a while and it is freed after some time, this will
1638 * mess the stack and values will not be restored properly. So use lock=1
1639 * to allocate temporary registers used internally by the programmer, and
1640 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1641 * to inform the compiler developer about a possible bug. This is an internal
1642 * feature for developing the compiler -- VR */
1644 int _TempReg_lock = 0;
1645 /*-----------------------------------------------------------------*/
1646 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1647 /*-----------------------------------------------------------------*/
1648 pCodeOp *pic16_popGetTempReg(int lock)
1653 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1655 // werror(W_POSSBUG2, __FILE__, __LINE__);
1658 _TempReg_lock += lock;
1663 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1664 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1665 PCOR(pcop)->r->wasUsed=1;
1666 PCOR(pcop)->r->isFree=0;
1668 /* push value on stack */
1669 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1677 /*-----------------------------------------------------------------*/
1678 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1679 /* is not part of f, but don't save if */
1681 /*-----------------------------------------------------------------*/
1682 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1688 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1691 // werror(W_POSSBUG2, __FILE__, __LINE__);
1694 _TempReg_lock += lock;
1699 i = bitVectFirstBit(f);
1702 /* bypass registers that are used by function */
1703 if(!bitVectBitValue(f, i)) {
1705 /* bypass registers that are already allocated for stack access */
1706 if(!bitVectBitValue(v, i)) {
1708 // debugf("getting register rIdx = %d\n", i);
1709 /* ok, get the operand */
1710 pcop = pic16_newpCodeOpReg( i );
1712 /* should never by NULL */
1713 assert( pcop != NULL );
1717 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1720 PCOR(pcop)->r->wasUsed=1;
1721 PCOR(pcop)->r->isFree=0;
1727 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1729 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1730 /* already used in previous steps, break */
1737 /* caller takes care of the following */
1738 // bitVectSetBit(v, i);
1741 /* push value on stack */
1742 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1743 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1759 /*-----------------------------------------------------------------*/
1760 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1761 /*-----------------------------------------------------------------*/
1762 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1764 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1766 _TempReg_lock -= lock;
1768 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1769 PCOR(pcop)->r->isFree = 1;
1771 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1774 /*-----------------------------------------------------------------*/
1775 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1776 /*-----------------------------------------------------------------*/
1777 pCodeOp *pic16_popGetLabel(unsigned int key)
1780 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1785 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1788 /*-----------------------------------------------------------------*/
1789 /* pic16_popCopyReg - copy a pcode operator */
1790 /*-----------------------------------------------------------------*/
1791 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1795 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1796 memcpy (pcor, pc, sizeof (pCodeOpReg));
1797 pcor->r->wasUsed = 1;
1799 //pcor->pcop.type = pc->pcop.type;
1801 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1802 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1804 pcor->pcop.name = NULL;
1807 //pcor->rIdx = pc->rIdx;
1808 //pcor->r->wasUsed=1;
1809 //pcor->instance = pc->instance;
1811 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1816 /*-----------------------------------------------------------------*/
1817 /* pic16_popGetLit - asm operator to pcode operator conversion */
1818 /*-----------------------------------------------------------------*/
1819 pCodeOp *pic16_popGetLit(int lit)
1821 return pic16_newpCodeOpLit(lit);
1824 /*-----------------------------------------------------------------*/
1825 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1826 /*-----------------------------------------------------------------*/
1827 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1829 return pic16_newpCodeOpLit2(lit, arg2);
1833 /*-----------------------------------------------------------------*/
1834 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1835 /*-----------------------------------------------------------------*/
1836 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1838 return pic16_newpCodeOpImmd(name, offset,index, 0);
1842 /*-----------------------------------------------------------------*/
1843 /* pic16_popGet - asm operator to pcode operator conversion */
1844 /*-----------------------------------------------------------------*/
1845 pCodeOp *pic16_popGetWithString(char *str)
1851 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1855 pcop = pic16_newpCodeOp(str,PO_STR);
1860 /*-----------------------------------------------------------------*/
1861 /* pic16_popRegFromString - */
1862 /*-----------------------------------------------------------------*/
1863 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1866 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1867 pcop->type = PO_DIR;
1869 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1870 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1875 pcop->name = Safe_calloc(1,strlen(str)+1);
1876 strcpy(pcop->name,str);
1878 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1880 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1882 /* make sure that register doesn't exist,
1883 * and operand isn't NULL
1884 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1885 if((PCOR(pcop)->r == NULL)
1887 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1888 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1889 // __FUNCTION__, __LINE__, str, size, offset);
1891 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1892 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1895 PCOR(pcop)->instance = offset;
1900 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1904 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1906 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1907 PCOR(pcop)->rIdx = rIdx;
1908 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1910 PCOR(pcop)->r->isFree = 0;
1911 PCOR(pcop)->r->wasUsed = 1;
1913 pcop->type = PCOR(pcop)->r->pc_type;
1918 /*---------------------------------------------------------------------------------*/
1919 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1921 /*---------------------------------------------------------------------------------*/
1922 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1927 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1929 /* comment the following check, so errors to throw up */
1930 // if(!pcop2)return NULL;
1932 temp = pic16_popGet(aop_dst, offset);
1933 pcop2->pcop2 = temp;
1940 /*--------------------------------------------------------------------------------.-*/
1941 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1942 /* VR 030601 , adapted by Hans Dorn */
1943 /*--------------------------------------------------------------------------------.-*/
1944 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1948 pcop2 = (pCodeOpReg2 *)src;
1956 /*---------------------------------------------------------------------------------*/
1957 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1958 /* movff instruction */
1959 /*---------------------------------------------------------------------------------*/
1960 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1965 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1966 pcop2->pcop2 = pic16_popCopyReg(dst);
1968 /* the pCodeOp may be already allocated */
1969 pcop2 = (pCodeOpReg2 *)(src);
1970 pcop2->pcop2 = (pCodeOp *)(dst);
1977 /*-----------------------------------------------------------------*/
1978 /* pic16_popGet - asm operator to pcode operator conversion */
1979 /*-----------------------------------------------------------------*/
1980 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1982 //char *s = buffer ;
1987 /* offset is greater than
1990 // if (offset > (aop->size - 1) &&
1991 // aop->type != AOP_LIT)
1992 // return NULL; //zero;
1994 /* depending on type */
1995 switch (aop->type) {
2001 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2002 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2009 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2010 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2011 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2012 PCOR(pcop)->r->wasUsed = 1;
2013 PCOR(pcop)->r->isFree = 0;
2015 PCOR(pcop)->instance = offset;
2016 pcop->type = PCOR(pcop)->r->pc_type;
2020 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2021 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2024 /* pCodeOp is already allocated from aopForSym */
2025 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2026 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2032 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2034 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2036 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2038 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2039 PCOR(pcop)->rIdx = rIdx;
2040 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2041 PCOR(pcop)->r->wasUsed=1;
2042 PCOR(pcop)->r->isFree=0;
2044 PCOR(pcop)->instance = offset;
2045 pcop->type = PCOR(pcop)->r->pc_type;
2046 // rs = aop->aopu.aop_reg[offset]->name;
2047 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2051 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2052 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2058 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2059 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2063 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2064 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2070 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2071 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2073 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2075 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2076 // pcop->type = PO_GPR_REGISTER;
2077 PCOR(pcop)->rIdx = rIdx;
2078 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2079 PCOR(pcop)->r->wasUsed=1;
2080 PCOR(pcop)->r->isFree=0;
2082 PCOR(pcop)->instance = offset;
2083 pcop->type = PCOR(pcop)->r->pc_type;
2085 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2086 rs = aop->aopu.aop_reg[offset]->name;
2087 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2092 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2094 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2095 PCOR(pcop)->instance = offset;
2096 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2097 //if(PCOR(pcop)->r == NULL)
2098 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2102 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2103 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2106 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2107 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2110 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2111 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2112 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2113 pcop->type = PCOR(pcop)->r->pc_type;
2114 pcop->name = PCOR(pcop)->r->name;
2120 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2122 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2123 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2124 switch( aop->aopu.pcop->type ) {
2125 case PO_DIR: PCOR(pcop)->instance += offset; break;
2126 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2131 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2132 assert( 0 ); /* should never reach here */;
2137 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2138 "pic16_popGet got unsupported aop->type");
2141 /*-----------------------------------------------------------------*/
2142 /* pic16_aopPut - puts a string for a aop */
2143 /*-----------------------------------------------------------------*/
2144 void pic16_aopPut (asmop *aop, char *s, int offset)
2151 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2153 if (aop->size && offset > ( aop->size - 1)) {
2154 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2155 "pic16_aopPut got offset > aop->size");
2159 /* will assign value to value */
2160 /* depending on where it is ofcourse */
2161 switch (aop->type) {
2164 sprintf(d,"(%s + %d)",
2165 aop->aopu.aop_dir,offset);
2166 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2169 sprintf(d,"%s",aop->aopu.aop_dir);
2172 DEBUGpic16_emitcode(";","%d",__LINE__);
2174 pic16_emitcode("movf","%s,w",s);
2175 pic16_emitcode("movwf","%s",d);
2178 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2179 if(offset >= aop->size) {
2180 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2183 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2186 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2193 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2194 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2197 strcmp(s,"r0") == 0 ||
2198 strcmp(s,"r1") == 0 ||
2199 strcmp(s,"r2") == 0 ||
2200 strcmp(s,"r3") == 0 ||
2201 strcmp(s,"r4") == 0 ||
2202 strcmp(s,"r5") == 0 ||
2203 strcmp(s,"r6") == 0 ||
2204 strcmp(s,"r7") == 0 )
2205 pic16_emitcode("mov","%s,%s ; %d",
2206 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2210 if(strcmp(s,"W")==0 )
2211 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2213 pic16_emitcode("movwf","%s",
2214 aop->aopu.aop_reg[offset]->name);
2216 if(strcmp(s,zero)==0) {
2217 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2219 } else if(strcmp(s,"W")==0) {
2220 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2221 pcop->type = PO_GPR_REGISTER;
2223 PCOR(pcop)->rIdx = -1;
2224 PCOR(pcop)->r = NULL;
2226 DEBUGpic16_emitcode(";","%d",__LINE__);
2227 pcop->name = Safe_strdup(s);
2228 pic16_emitpcode(POC_MOVFW,pcop);
2229 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2230 } else if(strcmp(s,one)==0) {
2231 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2232 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2234 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2242 if (aop->type == AOP_DPTR2)
2248 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2249 "pic16_aopPut writting to code space");
2253 while (offset > aop->coff) {
2255 pic16_emitcode ("inc","dptr");
2258 while (offset < aop->coff) {
2260 pic16_emitcode("lcall","__decdptr");
2265 /* if not in accumulater */
2268 pic16_emitcode ("movx","@dptr,a");
2270 if (aop->type == AOP_DPTR2)
2278 while (offset > aop->coff) {
2280 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2282 while (offset < aop->coff) {
2284 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2290 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2295 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2297 if (strcmp(s,"r0") == 0 ||
2298 strcmp(s,"r1") == 0 ||
2299 strcmp(s,"r2") == 0 ||
2300 strcmp(s,"r3") == 0 ||
2301 strcmp(s,"r4") == 0 ||
2302 strcmp(s,"r5") == 0 ||
2303 strcmp(s,"r6") == 0 ||
2304 strcmp(s,"r7") == 0 ) {
2306 sprintf(buffer,"a%s",s);
2307 pic16_emitcode("mov","@%s,%s",
2308 aop->aopu.aop_ptr->name,buffer);
2310 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2315 if (strcmp(s,"a") == 0)
2316 pic16_emitcode("push","acc");
2318 pic16_emitcode("push","%s",s);
2323 /* if bit variable */
2324 if (!aop->aopu.aop_dir) {
2325 pic16_emitcode("clr","a");
2326 pic16_emitcode("rlc","a");
2329 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2332 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2335 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2337 lbl = newiTempLabel(NULL);
2339 if (strcmp(s,"a")) {
2342 pic16_emitcode("clr","c");
2343 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2344 pic16_emitcode("cpl","c");
2345 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2346 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2353 if (strcmp(aop->aopu.aop_str[offset],s))
2354 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2359 if (!offset && (strcmp(s,"acc") == 0))
2362 if (strcmp(aop->aopu.aop_str[offset],s))
2363 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2367 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2368 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2369 // "pic16_aopPut got unsupported aop->type");
2375 /*-----------------------------------------------------------------*/
2376 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2377 /*-----------------------------------------------------------------*/
2378 void pic16_mov2w (asmop *aop, int offset)
2380 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2383 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2385 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2388 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2390 if(is_LitAOp(src)) {
2391 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2392 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2394 if(pic16_sameRegsOfs(src, dst, offset))return;
2395 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2396 pic16_popGet(dst, offset)));
2400 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2402 if(is_LitAOp(src)) {
2403 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2404 pic16_emitpcode(POC_MOVWF, dst);
2406 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2410 void pic16_testStackOverflow(void)
2412 #define GSTACK_TEST_NAME "_gstack_test"
2414 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2419 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2420 sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2421 // strcpy(sym->rname, GSTACK_TEST_NAME);
2422 checkAddSym(&externs, sym);
2427 /* push pcop into stack */
2428 void pic16_pushpCodeOp(pCodeOp *pcop)
2430 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2431 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2432 if(pic16_options.gstack)
2433 pic16_testStackOverflow();
2437 /* pop pcop from stack */
2438 void pic16_poppCodeOp(pCodeOp *pcop)
2440 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2441 if(pic16_options.gstack)
2442 pic16_testStackOverflow();
2446 /*-----------------------------------------------------------------*/
2447 /* pushw - pushes wreg to stack */
2448 /*-----------------------------------------------------------------*/
2451 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2452 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2453 if(pic16_options.gstack)
2454 pic16_testStackOverflow();
2458 /*-----------------------------------------------------------------*/
2459 /* pushaop - pushes aop to stack */
2460 /*-----------------------------------------------------------------*/
2461 void pushaop(asmop *aop, int offset)
2463 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2465 if(is_LitAOp(aop)) {
2466 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2467 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2469 pic16_emitpcode(POC_MOVFF,
2470 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2473 if(pic16_options.gstack)
2474 pic16_testStackOverflow();
2477 /*-----------------------------------------------------------------*/
2478 /* popaop - pops aop from stack */
2479 /*-----------------------------------------------------------------*/
2480 void popaop(asmop *aop, int offset)
2482 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2483 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2484 if(pic16_options.gstack)
2485 pic16_testStackOverflow();
2488 void popaopidx(asmop *aop, int offset, int index)
2492 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2494 if(STACK_MODEL_LARGE)ofs++;
2496 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2497 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2498 if(pic16_options.gstack)
2499 pic16_testStackOverflow();
2502 #if !(USE_GENERIC_SIGNED_SHIFT)
2503 /*-----------------------------------------------------------------*/
2504 /* reAdjustPreg - points a register back to where it should */
2505 /*-----------------------------------------------------------------*/
2506 static void reAdjustPreg (asmop *aop)
2510 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2512 if ((size = aop->size) <= 1)
2515 switch (aop->type) {
2519 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2523 if (aop->type == AOP_DPTR2)
2529 pic16_emitcode("lcall","__decdptr");
2532 if (aop->type == AOP_DPTR2)
2544 /*-----------------------------------------------------------------*/
2545 /* opIsGptr: returns non-zero if the passed operand is */
2546 /* a generic pointer type. */
2547 /*-----------------------------------------------------------------*/
2548 static int opIsGptr(operand *op)
2550 sym_link *type = operandType(op);
2552 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2553 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2561 /*-----------------------------------------------------------------*/
2562 /* pic16_getDataSize - get the operand data size */
2563 /*-----------------------------------------------------------------*/
2564 int pic16_getDataSize(operand *op)
2566 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2569 return AOP_SIZE(op);
2571 // tsd- in the pic port, the genptr size is 1, so this code here
2572 // fails. ( in the 8051 port, the size was 4).
2575 size = AOP_SIZE(op);
2576 if (size == GPTRSIZE)
2578 sym_link *type = operandType(op);
2579 if (IS_GENPTR(type))
2581 /* generic pointer; arithmetic operations
2582 * should ignore the high byte (pointer type).
2585 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2592 /*-----------------------------------------------------------------*/
2593 /* pic16_outAcc - output Acc */
2594 /*-----------------------------------------------------------------*/
2595 void pic16_outAcc(operand *result)
2598 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2599 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2602 size = pic16_getDataSize(result);
2604 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2607 /* unsigned or positive */
2609 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2614 /*-----------------------------------------------------------------*/
2615 /* pic16_outBitC - output a bit C */
2616 /* Move to result the value of Carry flag -- VR */
2617 /*-----------------------------------------------------------------*/
2618 void pic16_outBitC(operand *result)
2622 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2624 /* if the result is bit */
2625 if (AOP_TYPE(result) == AOP_CRY) {
2626 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2627 pic16_aopPut(AOP(result),"c",0);
2630 i = AOP_SIZE(result);
2632 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2634 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2638 /*-----------------------------------------------------------------*/
2639 /* pic16_outBitOp - output a bit from Op */
2640 /* Move to result the value of set/clr op -- VR */
2641 /*-----------------------------------------------------------------*/
2642 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2646 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2648 /* if the result is bit */
2649 if (AOP_TYPE(result) == AOP_CRY) {
2650 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2651 pic16_aopPut(AOP(result),"c",0);
2654 i = AOP_SIZE(result);
2656 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2658 pic16_emitpcode(POC_RRCF, pcop);
2659 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2663 /*-----------------------------------------------------------------*/
2664 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2665 /*-----------------------------------------------------------------*/
2666 void pic16_toBoolean(operand *oper)
2668 int size = AOP_SIZE(oper) - 1;
2671 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2673 if ( AOP_TYPE(oper) != AOP_ACC) {
2674 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2677 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2681 /*-----------------------------------------------------------------*/
2682 /* genUminusFloat - unary minus for floating points */
2683 /*-----------------------------------------------------------------*/
2684 static void genUminusFloat(operand *op,operand *result)
2686 int size ,offset =0 ;
2689 /* for this we just need to flip the
2690 first it then copy the rest in place */
2691 size = AOP_SIZE(op);
2692 assert( size == AOP_SIZE(result) );
2695 pic16_mov2f(AOP(result), AOP(op), offset);
2699 /* toggle the MSB's highest bit */
2700 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2703 /*-----------------------------------------------------------------*/
2704 /* genUminus - unary minus code generation */
2705 /*-----------------------------------------------------------------*/
2706 static void genUminus (iCode *ic)
2709 sym_link *optype, *rtype;
2716 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2717 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2719 /* if both in bit space then special case */
2720 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2721 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2723 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2724 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2725 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2729 optype = operandType(IC_LEFT(ic));
2730 rtype = operandType(IC_RESULT(ic));
2733 /* if float then do float stuff */
2734 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2735 if(IS_FIXED(optype))
2736 debugf("implement fixed16x16 type\n", 0);
2738 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2742 /* otherwise subtract from zero by taking the 2's complement */
2743 size = AOP_SIZE(IC_LEFT(ic));
2744 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2745 label = newiTempLabel ( NULL );
2747 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2748 for (i=size-1; i > 0; i--) {
2749 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2751 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2752 for (i=1; i < size; i++) {
2753 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2754 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2757 for (i=size-1; i >= 0; i--) {
2758 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2759 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2762 for (i=0; i < size-2; i++) {
2763 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2764 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2766 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2768 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2771 pic16_emitpLabel (label->key);
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 /* saveRegisters - will look for a call and save the registers */
2782 /*-----------------------------------------------------------------*/
2783 static void saveRegisters(iCode *lic)
2790 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2792 for (ic = lic ; ic ; ic = ic->next)
2793 if (ic->op == CALL || ic->op == PCALL)
2797 fprintf(stderr,"found parameter push with no function call\n");
2801 /* if the registers have been saved already then
2803 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2806 /* find the registers in use at this time
2807 and push them away to safety */
2808 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2812 if (options.useXstack) {
2813 if (bitVectBitValue(rsave,R0_IDX))
2814 pic16_emitcode("mov","b,r0");
2815 pic16_emitcode("mov","r0,%s",spname);
2816 for (i = 0 ; i < pic16_nRegs ; i++) {
2817 if (bitVectBitValue(rsave,i)) {
2819 pic16_emitcode("mov","a,b");
2821 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2822 pic16_emitcode("movx","@r0,a");
2823 pic16_emitcode("inc","r0");
2826 pic16_emitcode("mov","%s,r0",spname);
2827 if (bitVectBitValue(rsave,R0_IDX))
2828 pic16_emitcode("mov","r0,b");
2830 //for (i = 0 ; i < pic16_nRegs ; i++) {
2831 // if (bitVectBitValue(rsave,i))
2832 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2835 dtype = operandType(IC_LEFT(ic));
2836 if (currFunc && dtype &&
2837 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2838 IFFUNC_ISISR(currFunc->type) &&
2841 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2844 /*-----------------------------------------------------------------*/
2845 /* unsaveRegisters - pop the pushed registers */
2846 /*-----------------------------------------------------------------*/
2847 static void unsaveRegisters (iCode *ic)
2852 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2853 /* find the registers in use at this time
2854 and push them away to safety */
2855 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2858 if (options.useXstack) {
2859 pic16_emitcode("mov","r0,%s",spname);
2860 for (i = pic16_nRegs ; i >= 0 ; i--) {
2861 if (bitVectBitValue(rsave,i)) {
2862 pic16_emitcode("dec","r0");
2863 pic16_emitcode("movx","a,@r0");
2865 pic16_emitcode("mov","b,a");
2867 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2871 pic16_emitcode("mov","%s,r0",spname);
2872 if (bitVectBitValue(rsave,R0_IDX))
2873 pic16_emitcode("mov","r0,b");
2875 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2876 // if (bitVectBitValue(rsave,i))
2877 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2884 /*-----------------------------------------------------------------*/
2886 /*-----------------------------------------------------------------*/
2887 static void pushSide(operand * oper, int size)
2890 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2892 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2893 if (AOP_TYPE(oper) != AOP_REG &&
2894 AOP_TYPE(oper) != AOP_DIR &&
2896 pic16_emitcode("mov","a,%s",l);
2897 pic16_emitcode("push","acc");
2899 pic16_emitcode("push","%s",l);
2904 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2906 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2907 pic16_emitpcode(POC_MOVFW, src);
2908 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2910 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2911 src, pic16_popGet(AOP(op), offset)));
2916 /*-----------------------------------------------------------------*/
2917 /* assignResultValue - assign results to oper, rescall==1 is */
2918 /* called from genCall() or genPcall() */
2919 /*-----------------------------------------------------------------*/
2920 static void assignResultValue(operand * oper, int rescall)
2922 int size = AOP_SIZE(oper);
2926 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2927 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2930 /* assign result from a call/pcall function() */
2932 /* function results are stored in a special order,
2933 * see top of file with Function return policy, or manual */
2936 /* 8-bits, result in WREG */
2937 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2940 /* 16-bits, result in PRODL:WREG */
2941 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2945 /* 24-bits, result in PRODH:PRODL:WREG */
2946 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2950 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2951 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2955 /* >32-bits, result on stack, and FSR0 points to beginning.
2956 * Fix stack when done */
2958 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2960 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2961 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2963 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2968 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2969 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2970 if(STACK_MODEL_LARGE) {
2972 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2976 int areg = 0; /* matching argument register */
2978 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2979 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2982 /* its called from genReceive (probably) -- VR */
2983 /* I hope this code will not be called from somewhere else in the future!
2984 * We manually set the pseudo stack pointer in genReceive. - dw
2986 if(!GpsuedoStkPtr && _G.useWreg) {
2987 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2989 /* The last byte in the assignment is in W */
2990 if(areg <= GpsuedoStkPtr) {
2992 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2994 // debugf("receive from WREG\n", 0);
2996 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2999 _G.stack_lat = AOP_SIZE(oper)-1;
3004 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3005 // debugf("receive from STACK\n", 0);
3012 /*-----------------------------------------------------------------*/
3013 /* genIpush - generate code for pushing this gets a little complex */
3014 /*-----------------------------------------------------------------*/
3015 static void genIpush (iCode *ic)
3017 // int size, offset=0;
3020 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3023 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3025 /* send to stack as normal */
3026 addSet(&_G.sendSet,ic);
3027 // addSetHead(&_G.sendSet,ic);
3028 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3033 int size, offset = 0 ;
3037 /* if this is not a parm push : ie. it is spill push
3038 and spill push is always done on the local stack */
3039 if (!ic->parmPush) {
3041 /* and the item is spilt then do nothing */
3042 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3045 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3046 size = AOP_SIZE(IC_LEFT(ic));
3047 /* push it on the stack */
3049 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3054 pic16_emitcode("push","%s",l);
3059 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3063 /*-----------------------------------------------------------------*/
3064 /* genIpop - recover the registers: can happen only for spilling */
3065 /*-----------------------------------------------------------------*/
3066 static void genIpop (iCode *ic)
3069 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3074 /* if the temp was not pushed then */
3075 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3078 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3079 size = AOP_SIZE(IC_LEFT(ic));
3082 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3085 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3090 /*-----------------------------------------------------------------*/
3091 /* unsaverbank - restores the resgister bank from stack */
3092 /*-----------------------------------------------------------------*/
3093 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3095 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3101 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3103 if (options.useXstack) {
3105 r = getFreePtr(ic,&aop,FALSE);
3108 pic16_emitcode("mov","%s,_spx",r->name);
3109 pic16_emitcode("movx","a,@%s",r->name);
3110 pic16_emitcode("mov","psw,a");
3111 pic16_emitcode("dec","%s",r->name);
3114 pic16_emitcode ("pop","psw");
3117 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3118 if (options.useXstack) {
3119 pic16_emitcode("movx","a,@%s",r->name);
3120 //pic16_emitcode("mov","(%s+%d),a",
3121 // regspic16[i].base,8*bank+regspic16[i].offset);
3122 pic16_emitcode("dec","%s",r->name);
3125 pic16_emitcode("pop",""); //"(%s+%d)",
3126 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3129 if (options.useXstack) {
3131 pic16_emitcode("mov","_spx,%s",r->name);
3132 pic16_freeAsmop(NULL,aop,ic,TRUE);
3138 /*-----------------------------------------------------------------*/
3139 /* saverbank - saves an entire register bank on the stack */
3140 /*-----------------------------------------------------------------*/
3141 static void saverbank (int bank, iCode *ic, bool pushPsw)
3143 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3149 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3150 if (options.useXstack) {
3153 r = getFreePtr(ic,&aop,FALSE);
3154 pic16_emitcode("mov","%s,_spx",r->name);
3158 for (i = 0 ; i < pic16_nRegs ;i++) {
3159 if (options.useXstack) {
3160 pic16_emitcode("inc","%s",r->name);
3161 //pic16_emitcode("mov","a,(%s+%d)",
3162 // regspic16[i].base,8*bank+regspic16[i].offset);
3163 pic16_emitcode("movx","@%s,a",r->name);
3165 pic16_emitcode("push","");// "(%s+%d)",
3166 //regspic16[i].base,8*bank+regspic16[i].offset);
3170 if (options.useXstack) {
3171 pic16_emitcode("mov","a,psw");
3172 pic16_emitcode("movx","@%s,a",r->name);
3173 pic16_emitcode("inc","%s",r->name);
3174 pic16_emitcode("mov","_spx,%s",r->name);
3175 pic16_freeAsmop (NULL,aop,ic,TRUE);
3178 pic16_emitcode("push","psw");
3180 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3188 static int wparamCmp(void *p1, void *p2)
3190 return (!strcmp((char *)p1, (char *)p2));
3193 int inWparamList(char *s)
3195 return isinSetWith(wparamList, s, wparamCmp);
3199 /*-----------------------------------------------------------------*/
3200 /* genCall - generates a call statement */
3201 /*-----------------------------------------------------------------*/
3202 static void genCall (iCode *ic)
3212 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3213 /* if caller saves & we have not saved then */
3214 // if (!ic->regsSaved)
3215 // saveRegisters(ic);
3217 /* initialise stackParms for IPUSH pushes */
3218 // stackParms = psuedoStkPtr;
3219 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3220 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3221 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3224 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3227 /* if send set is not empty the assign */
3230 int psuedoStkPtr=-1;
3231 int firstTimeThruLoop = 1;
3234 /* reverse sendSet if function is not reentrant */
3235 if(!IFFUNC_ISREENT(ftype))
3236 _G.sendSet = reverseSet(_G.sendSet);
3238 /* First figure how many parameters are getting passed */
3242 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3246 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3247 size = AOP_SIZE(IC_LEFT(sic));
3251 /* pass the last byte through WREG */
3255 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3256 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3257 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3259 if(!firstTimeThruLoop) {
3260 /* If this is not the first time we've been through the loop
3261 * then we need to save the parameter in a temporary
3262 * register. The last byte of the last parameter is
3266 // --psuedoStkPtr; // sanity check
3270 firstTimeThruLoop=0;
3272 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3277 /* all arguments are passed via stack */
3281 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3282 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3283 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3285 // pushaop(AOP(IC_LEFT(sic)), size);
3286 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3293 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3297 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3298 pushw(); /* save last parameter to stack if functions has varargs */
3302 } else use_wreg = 0;
3304 _G.stackRegSet = _G.sendSet;
3309 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3313 /* if we need to assign a result value */
3314 if ((IS_ITEMP(IC_RESULT(ic))
3315 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3316 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3317 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3320 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3323 assignResultValue(IC_RESULT(ic), 1);
3325 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3326 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3328 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3331 if(!stackParms && ic->parmBytes) {
3332 stackParms = ic->parmBytes;
3335 stackParms -= use_wreg;
3338 if(stackParms == 1) {
3339 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3341 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3342 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3344 if(STACK_MODEL_LARGE) {
3346 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3351 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3354 /* adjust the stack for parameters if required */
3355 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3358 /* if register bank was saved then pop them */
3360 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3362 /* if we hade saved some registers then unsave them */
3363 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3364 unsaveRegisters (ic);
3370 /*-----------------------------------------------------------------*/
3371 /* genPcall - generates a call by pointer statement */
3372 /* new version, created from genCall - HJD */
3373 /*-----------------------------------------------------------------*/
3374 static void genPcall (iCode *ic)
3376 sym_link *ftype, *fntype;
3378 symbol *retlbl = newiTempLabel(NULL);
3379 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3383 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3384 fntype = operandType( IC_LEFT(ic) )->next;
3386 /* if send set is not empty the assign */
3389 int psuedoStkPtr=-1;
3391 /* reverse sendSet if function is not reentrant */
3392 if(!IFFUNC_ISREENT(fntype))
3393 _G.sendSet = reverseSet(_G.sendSet);
3397 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3400 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3401 size = AOP_SIZE(IC_LEFT(sic));
3404 /* all parameters are passed via stack, since WREG is clobbered
3405 * by the calling sequence */
3407 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3408 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3409 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3411 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3415 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3418 _G.stackRegSet = _G.sendSet;
3422 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3424 // push return address
3425 // push $ on return stack, then replace with retlbl
3427 /* Thanks to Thorsten Klose for pointing out that the following
3428 * snippet should be interrupt safe */
3429 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3430 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3432 pic16_emitpcodeNULLop(POC_PUSH);
3434 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3435 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3436 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3437 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3438 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3439 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3442 /* restore interrupt control register */
3443 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3444 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3446 /* make the call by writing the pointer into pc */
3447 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3448 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3450 // note: MOVFF to PCL not allowed
3451 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3452 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3455 /* return address is here: (X) */
3456 pic16_emitpLabelFORCE(retlbl->key);
3458 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3461 /* if we need assign a result value */
3462 if ((IS_ITEMP(IC_RESULT(ic))
3463 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3464 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3465 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3468 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3471 assignResultValue(IC_RESULT(ic), 1);
3473 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3474 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3476 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3479 // stackParms -= use_wreg;
3482 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3483 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3484 if(STACK_MODEL_LARGE) {
3486 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3491 /*-----------------------------------------------------------------*/
3492 /* resultRemat - result is rematerializable */
3493 /*-----------------------------------------------------------------*/
3494 static int resultRemat (iCode *ic)
3496 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3497 if (SKIP_IC(ic) || ic->op == IFX)
3500 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3501 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3502 if (sym->remat && !POINTER_SET(ic))
3509 #if defined(__BORLANDC__) || defined(_MSC_VER)
3510 #define STRCASECMP stricmp
3512 #define STRCASECMP strcasecmp
3516 /*-----------------------------------------------------------------*/
3517 /* inExcludeList - return 1 if the string is in exclude Reg list */
3518 /*-----------------------------------------------------------------*/
3519 static bool inExcludeList(char *s)
3521 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3524 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3525 if (options.excludeRegs[i] &&
3526 STRCASECMP(options.excludeRegs[i],"none") == 0)
3529 for ( i = 0 ; options.excludeRegs[i]; i++) {
3530 if (options.excludeRegs[i] &&
3531 STRCASECMP(s,options.excludeRegs[i]) == 0)
3538 /*-----------------------------------------------------------------*/
3539 /* genFunction - generated code for function entry */
3540 /*-----------------------------------------------------------------*/
3541 static void genFunction (iCode *ic)
3547 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3549 pic16_labelOffset += (max_key+4);
3554 ftype = operandType(IC_LEFT(ic));
3555 sym = OP_SYMBOL(IC_LEFT(ic));
3557 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3558 /* create an absolute section at the interrupt vector:
3559 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3564 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3566 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3567 sprintf(asymname, "ivec_%s", sym->name);
3569 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3571 /* when an interrupt is declared as naked, do not emit the special
3572 * wrapper segment at vector address. The user should take care for
3573 * this instead. -- VR */
3575 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3576 asym = newSymbol(asymname, 0);
3577 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3578 pic16_addpBlock( apb );
3580 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3581 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3582 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3583 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3584 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3586 /* mark the end of this tiny function */
3587 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3589 sprintf(asymname, "%s", sym->rname);
3595 abSym = Safe_calloc(1, sizeof(absSym));
3596 strcpy(abSym->name, asymname);
3598 switch( FUNC_INTNO(sym->type) ) {
3599 case 0: abSym->address = 0x000000; break;
3600 case 1: abSym->address = 0x000008; break;
3601 case 2: abSym->address = 0x000018; break;
3604 // fprintf(stderr, "no interrupt number is given\n");
3605 abSym->address = -1; break;
3608 /* relocate interrupt vectors if needed */
3609 if(abSym->address != -1)
3610 abSym->address += pic16_options.ivt_loc;
3612 addSet(&absSymSet, abSym);
3616 /* create the function header */
3617 pic16_emitcode(";","-----------------------------------------");
3618 pic16_emitcode(";"," function %s",sym->name);
3619 pic16_emitcode(";","-----------------------------------------");
3621 pic16_emitcode("","%s:",sym->rname);
3622 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3627 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3628 if(!strcmp(ab->name, sym->rname)) {
3629 pic16_pBlockConvert2Absolute(pb);
3635 if(IFFUNC_ISNAKED(ftype)) {
3636 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3640 /* if critical function then turn interrupts off */
3641 if (IFFUNC_ISCRITICAL(ftype)) {
3642 //pic16_emitcode("clr","ea");
3645 currFunc = sym; /* update the currFunc symbol */
3646 _G.fregsUsed = sym->regsUsed;
3647 _G.sregsAlloc = newBitVect(128);
3650 /* if this is an interrupt service routine then
3651 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3652 if (IFFUNC_ISISR(sym->type)) {
3653 _G.usefastretfie = 1; /* use shadow registers by default */
3655 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3656 if(!FUNC_ISSHADOWREGS(sym->type)) {
3657 /* do not save WREG,STATUS,BSR for high priority interrupts
3658 * because they are stored in the hardware shadow registers already */
3659 _G.usefastretfie = 0;
3660 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3661 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3662 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3665 /* these should really be optimized somehow, because not all
3666 * interrupt handlers modify them */
3667 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3668 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3669 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3670 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3672 // pic16_pBlockConvert2ISR(pb);
3675 /* emit code to setup stack frame if user enabled,
3676 * and function is not main() */
3678 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3679 if(strcmp(sym->name, "main")) {
3681 || !options.ommitFramePtr
3683 || IFFUNC_ARGS(sym->type)
3684 || FUNC_HASSTACKPARM(sym->etype)
3686 /* setup the stack frame */
3687 if(STACK_MODEL_LARGE)
3688 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3689 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3691 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3692 if(STACK_MODEL_LARGE)
3693 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3697 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3700 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3702 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3703 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3705 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3708 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3709 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3716 /* if callee-save to be used for this function
3717 * then save the registers being used in this function */
3718 // if (IFFUNC_CALLEESAVES(sym->type))
3722 /* if any registers used */
3723 if (sym->regsUsed) {
3724 /* save the registers used */
3725 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3726 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3727 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3728 if (bitVectBitValue(sym->regsUsed,i)) {
3729 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3732 if(!pic16_regWithIdx(i)->wasUsed) {
3733 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3734 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3735 pic16_regWithIdx(i)->wasUsed = 1;
3739 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3743 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3744 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3747 /*-----------------------------------------------------------------*/
3748 /* genEndFunction - generates epilogue for functions */
3749 /*-----------------------------------------------------------------*/
3750 static void genEndFunction (iCode *ic)
3752 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3756 if(IFFUNC_ISNAKED(sym->type)) {
3757 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3763 /* add code for ISCRITICAL */
3764 if(IFFUNC_ISCRITICAL(sym->type)) {
3765 /* if critical function, turn on interrupts */
3767 /* TODO: add code here -- VR */
3770 // sym->regsUsed = _G.fregsUsed;
3772 /* now we need to restore the registers */
3773 /* if any registers used */
3775 /* first restore registers that might be used for stack access */
3776 if(_G.sregsAllocSet) {
3779 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3780 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3781 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3785 if (sym->regsUsed) {
3788 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3789 /* restore registers used */
3790 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3791 for ( i = sym->regsUsed->size; i >= 0; i--) {
3792 if (bitVectBitValue(sym->regsUsed,i)) {
3793 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3797 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3802 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3804 if (sym->stack == 1) {
3805 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3806 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3808 // we have to add more than one...
3809 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3810 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3811 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3813 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3814 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3815 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3819 if(strcmp(sym->name, "main")) {
3821 || !options.ommitFramePtr
3823 || IFFUNC_ARGS(sym->type)
3824 || FUNC_HASSTACKPARM(sym->etype)
3826 /* restore stack frame */
3827 if(STACK_MODEL_LARGE)
3828 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3829 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3835 if (IFFUNC_ISISR(sym->type)) {
3836 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3837 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3838 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3839 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3841 if(!FUNC_ISSHADOWREGS(sym->type)) {
3842 /* do not restore interrupt vector for WREG,STATUS,BSR
3843 * for high priority interrupt, see genFunction */
3844 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3845 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3846 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3848 // _G.interruptvector = 0; /* sanity check */
3851 /* if debug then send end of function */
3852 /* if (options.debug && currFunc) */
3854 debugFile->writeEndFunction (currFunc, ic, 1);
3857 if(_G.usefastretfie)
3858 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3860 pic16_emitpcodeNULLop(POC_RETFIE);
3862 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3864 _G.usefastretfie = 0;
3868 if (IFFUNC_ISCRITICAL(sym->type)) {
3869 pic16_emitcode("setb","ea");
3872 /* if debug then send end of function */
3874 debugFile->writeEndFunction (currFunc, ic, 1);
3877 /* insert code to restore stack frame, if user enabled it
3878 * and function is not main() */
3881 pic16_emitpcodeNULLop(POC_RETURN);
3883 /* Mark the end of a function */
3884 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3888 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3890 unsigned long lit=1;
3895 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3896 if(AOP_TYPE(op) == AOP_LIT) {
3897 if(!IS_FLOAT(operandType( op ))) {
3898 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3901 unsigned long lit_int;
3905 /* take care if literal is a float */
3906 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3912 if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
3913 pic16_emitpcode(POC_CLRF, dest);
3915 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3916 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3919 if(dest->type == PO_WREG && (offset == 0)) {
3920 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3923 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3927 /*-----------------------------------------------------------------*/
3928 /* genRet - generate code for return statement */
3929 /*-----------------------------------------------------------------*/
3930 static void genRet (iCode *ic)
3936 /* if we have no return value then
3937 * just generate the "ret" */
3942 /* we have something to return then
3943 * move the return value into place */
3944 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3945 size = AOP_SIZE(IC_LEFT(ic));
3949 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3952 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3955 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3957 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3960 /* >32-bits, setup stack and FSR0 */
3962 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3963 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3965 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3967 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3972 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3973 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3975 if(STACK_MODEL_LARGE) {
3976 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3977 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3979 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3984 /* old code, left here for reference -- VR */
3988 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3990 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3991 pic16_emitpcomment("push %s",l);
3994 DEBUGpic16_emitcode(";", "%d", __LINE__);
3995 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3996 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3998 if (strcmp(fReturn[offset],l)) {
3999 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4000 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4001 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4003 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4007 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4017 if (strcmp(fReturn[pushed],"a"))
4018 pic16_emitcode("pop",fReturn[pushed]);
4020 pic16_emitcode("pop","acc");
4026 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4029 /* generate a jump to the return label
4030 * if the next is not the return statement */
4031 if (!(ic->next && ic->next->op == LABEL
4032 && IC_LABEL(ic->next) == returnLabel)) {
4034 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4035 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4039 /*-----------------------------------------------------------------*/
4040 /* genLabel - generates a label */
4041 /*-----------------------------------------------------------------*/
4042 static void genLabel (iCode *ic)
4046 /* special case never generate */
4047 if (IC_LABEL(ic) == entryLabel)
4050 pic16_emitpLabel(IC_LABEL(ic)->key);
4051 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4054 /*-----------------------------------------------------------------*/
4055 /* genGoto - generates a goto */
4056 /*-----------------------------------------------------------------*/
4058 static void genGoto (iCode *ic)
4061 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4062 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4066 /*-----------------------------------------------------------------*/
4067 /* genMultbits :- multiplication of bits */
4068 /*-----------------------------------------------------------------*/
4069 static void genMultbits (operand *left,
4075 if(!pic16_sameRegs(AOP(result),AOP(right)))
4076 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4078 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4079 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4080 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4085 /*-----------------------------------------------------------------*/
4086 /* genMultOneByte : 8 bit multiplication & division */
4087 /*-----------------------------------------------------------------*/
4088 static void genMultOneByte (operand *left,
4094 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4095 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4097 /* (if two literals, the value is computed before) */
4098 /* if one literal, literal on the right */
4099 if (AOP_TYPE(left) == AOP_LIT){
4105 /* size is already checked in genMult == 1 */
4106 // size = AOP_SIZE(result);
4108 if (AOP_TYPE(right) == AOP_LIT){
4109 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4110 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4111 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4112 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4114 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4115 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4116 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4117 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4120 pic16_genMult8X8_8 (left, right,result);
4123 /*-----------------------------------------------------------------*/
4124 /* genMultOneWord : 16 bit multiplication */
4125 /*-----------------------------------------------------------------*/
4126 static void genMultOneWord (operand *left,
4131 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4132 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4134 /* (if two literals, the value is computed before)
4135 * if one literal, literal on the right */
4136 if (AOP_TYPE(left) == AOP_LIT){
4142 /* size is checked already == 2 */
4143 // size = AOP_SIZE(result);
4145 if (AOP_TYPE(right) == AOP_LIT) {
4146 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4147 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4148 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4149 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4151 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4152 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4153 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4154 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4157 pic16_genMult16X16_16(left, right,result);
4160 /*-----------------------------------------------------------------*/
4161 /* genMultOneLong : 32 bit multiplication */
4162 /*-----------------------------------------------------------------*/
4163 static void genMultOneLong (operand *left,
4168 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4169 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4171 /* (if two literals, the value is computed before)
4172 * if one literal, literal on the right */
4173 if (AOP_TYPE(left) == AOP_LIT){
4179 /* size is checked already == 4 */
4180 // size = AOP_SIZE(result);
4182 if (AOP_TYPE(right) == AOP_LIT) {
4183 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4184 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4185 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4186 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4188 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4189 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4190 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4191 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4194 pic16_genMult32X32_32(left, right,result);
4199 /*-----------------------------------------------------------------*/
4200 /* genMult - generates code for multiplication */
4201 /*-----------------------------------------------------------------*/
4202 static void genMult (iCode *ic)
4204 operand *left = IC_LEFT(ic);
4205 operand *right = IC_RIGHT(ic);
4206 operand *result= IC_RESULT(ic);
4209 /* assign the amsops */
4210 pic16_aopOp (left,ic,FALSE);
4211 pic16_aopOp (right,ic,FALSE);
4212 pic16_aopOp (result,ic,TRUE);
4214 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4216 /* special cases first *
4218 if (AOP_TYPE(left) == AOP_CRY
4219 && AOP_TYPE(right)== AOP_CRY) {
4220 genMultbits(left,right,result);
4224 /* if both are of size == 1 */
4225 if(AOP_SIZE(left) == 1
4226 && AOP_SIZE(right) == 1) {
4227 genMultOneByte(left,right,result);
4231 /* if both are of size == 2 */
4232 if(AOP_SIZE(left) == 2
4233 && AOP_SIZE(right) == 2) {
4234 genMultOneWord(left, right, result);
4238 /* if both are of size == 4 */
4239 if(AOP_SIZE(left) == 4
4240 && AOP_SIZE(right) == 4) {
4241 genMultOneLong(left, right, result);
4245 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4248 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4249 /* should have been converted to function call */
4253 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4254 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4255 pic16_freeAsmop(result,NULL,ic,TRUE);
4258 /*-----------------------------------------------------------------*/
4259 /* genDivbits :- division of bits */
4260 /*-----------------------------------------------------------------*/
4261 static void genDivbits (operand *left,
4268 /* the result must be bit */
4269 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4270 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4274 pic16_emitcode("div","ab");
4275 pic16_emitcode("rrc","a");
4276 pic16_aopPut(AOP(result),"c",0);
4279 /*-----------------------------------------------------------------*/
4280 /* genDivOneByte : 8 bit division */
4281 /*-----------------------------------------------------------------*/
4282 static void genDivOneByte (operand *left,
4286 sym_link *opetype = operandType(result);
4291 /* result = divident / divisor
4292 * - divident may be a register or a literal,
4293 * - divisor may be a register or a literal,
4294 * so there are 3 cases (literal / literal is optimized
4295 * by the front-end) to handle.
4296 * In addition we must handle signed and unsigned, which
4297 * result in 6 final different cases -- VR */
4301 size = AOP_SIZE(result) - 1;
4303 /* signed or unsigned */
4304 if (SPEC_USIGN(opetype)) {
4305 pCodeOp *pct1, /* count */
4308 symbol *label1, *label2, *label3;;
4311 /* unsigned is easy */
4313 pct1 = pic16_popGetTempReg(1);
4314 pct2 = pic16_popGetTempReg(1);
4315 pct3 = pic16_popGetTempReg(1);
4317 label1 = newiTempLabel(NULL);
4318 label2 = newiTempLabel(NULL);
4319 label3 = newiTempLabel(NULL);
4321 /* the following algorithm is extracted from divuint.c */
4323 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4324 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4326 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4328 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4330 pic16_emitpLabel(label1->key);
4333 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4337 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4341 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4343 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4344 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4346 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4347 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4348 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4350 pic16_emitpLabel( label3->key );
4351 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4352 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4356 pic16_emitpLabel(label2->key);
4357 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4358 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4359 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4361 /* result is in wreg */
4362 if(AOP_TYPE(result) != AOP_ACC)
4363 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4365 pic16_popReleaseTempReg( pct3, 1);
4366 pic16_popReleaseTempReg( pct2, 1);
4367 pic16_popReleaseTempReg( pct1, 1);
4372 /* signed is a little bit more difficult */
4374 /* save the signs of the operands */
4375 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4377 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4378 pic16_emitcode("push","acc"); /* save it on the stack */
4380 /* now sign adjust for both left & right */
4381 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4383 lbl = newiTempLabel(NULL);
4384 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4385 pic16_emitcode("cpl","a");
4386 pic16_emitcode("inc","a");
4387 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4388 pic16_emitcode("mov","b,a");
4390 /* sign adjust left side */
4391 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4394 lbl = newiTempLabel(NULL);
4395 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4396 pic16_emitcode("cpl","a");
4397 pic16_emitcode("inc","a");
4398 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4400 /* now the division */
4401 pic16_emitcode("div","ab");
4402 /* we are interested in the lower order
4404 pic16_emitcode("mov","b,a");
4405 lbl = newiTempLabel(NULL);
4406 pic16_emitcode("pop","acc");
4407 /* if there was an over flow we don't
4408 adjust the sign of the result */
4409 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4410 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4412 pic16_emitcode("clr","a");
4413 pic16_emitcode("subb","a,b");
4414 pic16_emitcode("mov","b,a");
4415 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4417 /* now we are done */
4418 pic16_aopPut(AOP(result),"b",0);
4420 pic16_emitcode("mov","c,b.7");
4421 pic16_emitcode("subb","a,acc");
4424 pic16_aopPut(AOP(result),"a",offset++);
4428 /*-----------------------------------------------------------------*/
4429 /* genDiv - generates code for division */
4430 /*-----------------------------------------------------------------*/
4431 static void genDiv (iCode *ic)
4433 operand *left = IC_LEFT(ic);
4434 operand *right = IC_RIGHT(ic);
4435 operand *result= IC_RESULT(ic);
4438 /* Division is a very lengthy algorithm, so it is better
4439 * to call support routines than inlining algorithm.
4440 * Division functions written here just in case someone
4441 * wants to inline and not use the support libraries -- VR */
4445 /* assign the amsops */
4446 pic16_aopOp (left,ic,FALSE);
4447 pic16_aopOp (right,ic,FALSE);
4448 pic16_aopOp (result,ic,TRUE);
4450 /* special cases first */
4452 if (AOP_TYPE(left) == AOP_CRY &&
4453 AOP_TYPE(right)== AOP_CRY) {
4454 genDivbits(left,right,result);
4458 /* if both are of size == 1 */
4459 if (AOP_SIZE(left) == 1 &&
4460 AOP_SIZE(right) == 1 ) {
4461 genDivOneByte(left,right,result);
4465 /* should have been converted to function call */
4468 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4469 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4470 pic16_freeAsmop(result,NULL,ic,TRUE);
4473 /*-----------------------------------------------------------------*/
4474 /* genModbits :- modulus of bits */
4475 /*-----------------------------------------------------------------*/
4476 static void genModbits (operand *left,
4484 werror(W_POSSBUG2, __FILE__, __LINE__);
4485 /* the result must be bit */
4486 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4487 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4491 pic16_emitcode("div","ab");
4492 pic16_emitcode("mov","a,b");
4493 pic16_emitcode("rrc","a");
4494 pic16_aopPut(AOP(result),"c",0);
4497 /*-----------------------------------------------------------------*/
4498 /* genModOneByte : 8 bit modulus */
4499 /*-----------------------------------------------------------------*/
4500 static void genModOneByte (operand *left,
4504 sym_link *opetype = operandType(result);
4509 werror(W_POSSBUG2, __FILE__, __LINE__);
4511 /* signed or unsigned */
4512 if (SPEC_USIGN(opetype)) {
4513 /* unsigned is easy */
4514 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4515 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4517 pic16_emitcode("div","ab");
4518 pic16_aopPut(AOP(result),"b",0);
4522 /* signed is a little bit more difficult */
4524 /* save the signs of the operands */
4525 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4528 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4529 pic16_emitcode("push","acc"); /* save it on the stack */
4531 /* now sign adjust for both left & right */
4532 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4535 lbl = newiTempLabel(NULL);
4536 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4537 pic16_emitcode("cpl","a");
4538 pic16_emitcode("inc","a");
4539 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4540 pic16_emitcode("mov","b,a");
4542 /* sign adjust left side */
4543 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4546 lbl = newiTempLabel(NULL);
4547 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4548 pic16_emitcode("cpl","a");
4549 pic16_emitcode("inc","a");
4550 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4552 /* now the multiplication */
4553 pic16_emitcode("div","ab");
4554 /* we are interested in the lower order
4556 lbl = newiTempLabel(NULL);
4557 pic16_emitcode("pop","acc");
4558 /* if there was an over flow we don't
4559 adjust the sign of the result */
4560 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4561 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4563 pic16_emitcode("clr","a");
4564 pic16_emitcode("subb","a,b");
4565 pic16_emitcode("mov","b,a");
4566 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4568 /* now we are done */
4569 pic16_aopPut(AOP(result),"b",0);
4573 /*-----------------------------------------------------------------*/
4574 /* genMod - generates code for division */
4575 /*-----------------------------------------------------------------*/
4576 static void genMod (iCode *ic)
4578 operand *left = IC_LEFT(ic);
4579 operand *right = IC_RIGHT(ic);
4580 operand *result= IC_RESULT(ic);
4584 /* assign the amsops */
4585 pic16_aopOp (left,ic,FALSE);
4586 pic16_aopOp (right,ic,FALSE);
4587 pic16_aopOp (result,ic,TRUE);
4589 /* special cases first */
4591 if (AOP_TYPE(left) == AOP_CRY &&
4592 AOP_TYPE(right)== AOP_CRY) {
4593 genModbits(left,right,result);
4597 /* if both are of size == 1 */
4598 if (AOP_SIZE(left) == 1 &&
4599 AOP_SIZE(right) == 1 ) {
4600 genModOneByte(left,right,result);
4604 /* should have been converted to function call */
4608 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4609 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4610 pic16_freeAsmop(result,NULL,ic,TRUE);
4613 /*-----------------------------------------------------------------*/
4614 /* genIfxJump :- will create a jump depending on the ifx */
4615 /*-----------------------------------------------------------------*/
4617 note: May need to add parameter to indicate when a variable is in bit space.
4619 static void genIfxJump (iCode *ic, char *jval)
4623 /* if true label then we jump if condition
4625 if ( IC_TRUE(ic) ) {
4627 if(strcmp(jval,"a") == 0)
4629 else if (strcmp(jval,"c") == 0)
4632 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4633 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4636 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4637 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4641 /* false label is present */
4642 if(strcmp(jval,"a") == 0)
4644 else if (strcmp(jval,"c") == 0)
4647 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4648 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4651 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4652 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4657 /* mark the icode as generated */
4661 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4665 /* if true label then we jump if condition
4667 if ( IC_TRUE(ic) ) {
4668 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4669 pic16_emitpcode(POC_BTFSC, jop);
4671 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4672 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4675 /* false label is present */
4676 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4677 pic16_emitpcode(POC_BTFSS, jop);
4679 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4680 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4684 /* mark the icode as generated */
4691 /*-----------------------------------------------------------------*/
4693 /*-----------------------------------------------------------------*/
4694 static void genSkip(iCode *ifx,int status_bit)
4696 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4700 if ( IC_TRUE(ifx) ) {
4701 switch(status_bit) {
4716 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4717 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4721 switch(status_bit) {
4735 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4736 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4743 /*-----------------------------------------------------------------*/
4745 /*-----------------------------------------------------------------*/
4746 static void genSkipc(resolvedIfx *rifx)
4748 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4758 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4759 rifx->generated = 1;
4762 #if !(USE_SIMPLE_GENCMP)
4763 /*-----------------------------------------------------------------*/
4765 /*-----------------------------------------------------------------*/
4766 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4768 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4773 if( (rifx->condition ^ invert_condition) & 1)
4778 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4779 rifx->generated = 1;
4784 /*-----------------------------------------------------------------*/
4786 /*-----------------------------------------------------------------*/
4787 static void genSkipz(iCode *ifx, int condition)
4798 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4800 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4803 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4805 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4810 #if !(USE_SIMPLE_GENCMP)
4811 /*-----------------------------------------------------------------*/
4813 /*-----------------------------------------------------------------*/
4814 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4820 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4822 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4825 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4826 rifx->generated = 1;
4831 /*-----------------------------------------------------------------*/
4832 /* genChkZeroes :- greater or less than comparison */
4833 /* For each byte in a literal that is zero, inclusive or the */
4834 /* the corresponding byte in the operand with W */
4835 /* returns true if any of the bytes are zero */
4836 /*-----------------------------------------------------------------*/
4837 static int genChkZeroes(operand *op, int lit, int size)
4844 i = (lit >> (size*8)) & 0xff;
4848 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4850 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4860 /*-----------------------------------------------------------------*/
4861 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4862 /* aop (if it's NOT a literal) or from lit (if */
4863 /* aop is a literal) */
4864 /*-----------------------------------------------------------------*/
4865 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4866 if (aop->type == AOP_LIT) {
4867 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4869 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4873 /*-----------------------------------------------------------------*/
4874 /* genCmp :- greater or less than comparison */
4875 /*-----------------------------------------------------------------*/
4877 #if USE_SIMPLE_GENCMP /* { */
4879 /* genCmp performs a left < right comparison, stores
4880 * the outcome in result (if != NULL) and generates
4881 * control flow code for the ifx (if != NULL).
4883 * This version leaves in sequences like
4884 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4885 * which should be optmized by the peephole
4886 * optimizer - RN 2005-01-01 */
4887 static void genCmp (operand *left,operand *right,
4888 operand *result, iCode *ifx, int sign)
4901 assert (left && right);
4902 assert (AOP_SIZE(left) == AOP_SIZE(right));
4904 size = AOP_SIZE(right) - 1;
4905 mask = (0x100UL << (size*8)) - 1;
4906 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4911 resolveIfx (&rIfx, ifx);
4913 /* handle for special cases */
4914 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4917 /**********************************************************************
4918 * handle bits - bit compares are promoted to int compares seemingly! *
4919 **********************************************************************/
4921 // THIS IS COMPLETELY UNTESTED!
4922 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4923 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4924 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4925 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4928 // 1 < {0,1} is false --> clear C by skipping the next instruction
4929 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4930 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4931 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4932 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4933 emitCLRC; // only skipped for left=0 && right=1
4935 goto correct_result_in_carry;
4939 /*************************************************
4940 * make sure that left is register (or the like) *
4941 *************************************************/
4942 if (!isAOP_REGlike(left)) {
4943 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4944 assert (isAOP_LIT(left));
4945 assert (isAOP_REGlike(right));
4946 // swap left and right
4947 // left < right <==> right > left <==> (right >= left + 1)
4948 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4950 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4951 // MAXVALUE < right? always false
4952 if (performedLt) emitCLRC; else emitSETC;
4953 goto correct_result_in_carry;
4956 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4957 // that's why we handled it above.
4964 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4965 } else if (isAOP_LIT(right)) {
4966 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4969 assert (isAOP_REGlike(left)); // left must be register or the like
4970 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4972 /*************************************************
4973 * special cases go here *
4974 *************************************************/
4976 if (isAOP_LIT(right)) {
4978 // unsigned comparison to a literal
4979 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4981 // unsigned left < 0? always false
4982 if (performedLt) emitCLRC; else emitSETC;
4983 goto correct_result_in_carry;
4986 // signed comparison to a literal
4987 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4988 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4989 // signed left < 0x80000000? always false
4990 if (performedLt) emitCLRC; else emitSETC;
4991 goto correct_result_in_carry;
4992 } else if (lit == 0) {
4993 // compare left < 0; set CARRY if SIGNBIT(left) is set
4994 if (performedLt) emitSETC; else emitCLRC;
4995 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4996 if (performedLt) emitCLRC; else emitSETC;
4997 goto correct_result_in_carry;
5000 } // right is literal
5002 /*************************************************
5003 * perform a general case comparison *
5004 * make sure we get CARRY==1 <==> left >= right *
5005 *************************************************/
5006 // compare most significant bytes
5007 //DEBUGpc ("comparing bytes at offset %d", size);
5009 // unsigned comparison
5010 mov2w_regOrLit (AOP(right), lit, size);
5011 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5013 // signed comparison
5014 // (add 2^n to both operands then perform an unsigned comparison)
5015 if (isAOP_LIT(right)) {
5016 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5017 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5019 if (litbyte == 0x80) {
5020 // left >= 0x80 -- always true, but more bytes to come
5021 pic16_mov2w (AOP(left), size);
5022 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5025 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5026 pic16_mov2w (AOP(left), size);
5027 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5028 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5031 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5032 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5033 pic16_mov2w (AOP(left), size);
5034 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5035 pic16_emitpcode (POC_MOVWF, pctemp);
5036 pic16_mov2w (AOP(right), size);
5037 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5038 pic16_emitpcode (POC_SUBFW, pctemp);
5039 //pic16_popReleaseTempReg(pctemp, 1);
5043 // compare remaining bytes (treat as unsigned case from above)
5044 templbl = newiTempLabel ( NULL );
5047 //DEBUGpc ("comparing bytes at offset %d", offs);
5048 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5049 mov2w_regOrLit (AOP(right), lit, offs);
5050 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5052 pic16_emitpLabel (templbl->key);
5053 goto result_in_carry;
5057 /****************************************************
5058 * now CARRY contains the result of the comparison: *
5059 * SUBWF sets CARRY iff *
5060 * F-W >= 0 <==> F >= W <==> !(F < W) *
5061 * (F=left, W=right) *
5062 ****************************************************/
5065 if (result && AOP_TYPE(result) != AOP_CRY) {
5066 // value will be stored
5069 // value wil only be used in the following genSkipc()
5070 rIfx.condition ^= 1;
5074 correct_result_in_carry:
5076 // assign result to variable (if neccessary)
5077 if (result && AOP_TYPE(result) != AOP_CRY) {
5078 //DEBUGpc ("assign result");
5079 size = AOP_SIZE(result);
5081 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5083 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5086 // perform conditional jump
5088 //DEBUGpc ("generate control flow");
5097 static void genCmp (operand *left,operand *right,
5098 operand *result, iCode *ifx, int sign)
5100 int size; //, offset = 0 ;
5101 unsigned long lit = 0L,i = 0;
5102 resolvedIfx rFalseIfx;
5103 // resolvedIfx rTrueIfx;
5105 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5108 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5109 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5115 resolveIfx(&rFalseIfx,ifx);
5116 truelbl = newiTempLabel(NULL);
5117 size = max(AOP_SIZE(left),AOP_SIZE(right));
5119 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5123 /* if literal is on the right then swap with left */
5124 if ((AOP_TYPE(right) == AOP_LIT)) {
5125 operand *tmp = right ;
5126 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5127 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5130 lit = (lit - 1) & mask;
5133 rFalseIfx.condition ^= 1;
5136 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5137 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5141 //if(IC_TRUE(ifx) == NULL)
5142 /* if left & right are bit variables */
5143 if (AOP_TYPE(left) == AOP_CRY &&
5144 AOP_TYPE(right) == AOP_CRY ) {
5145 assert (0 && "bit variables used in genCmp");
5146 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5147 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5149 /* subtract right from left if at the
5150 end the carry flag is set then we know that
5151 left is greater than right */
5153 symbol *lbl = newiTempLabel(NULL);
5156 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5157 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5161 if(AOP_TYPE(right) == AOP_LIT) {
5163 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5165 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5172 genSkipCond(&rFalseIfx,left,size-1,7);
5174 /* no need to compare to 0...*/
5175 /* NOTE: this is a de-generate compare that most certainly
5176 * creates some dead code. */
5177 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5179 if(ifx) ifx->generated = 1;
5186 //i = (lit >> (size*8)) & 0xff;
5187 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5189 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5191 i = ((0-lit) & 0xff);
5194 /* lit is 0x7f, all signed chars are less than
5195 * this except for 0x7f itself */
5196 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5197 genSkipz2(&rFalseIfx,0);
5199 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5200 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5201 genSkipc(&rFalseIfx);
5206 genSkipz2(&rFalseIfx,1);
5208 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5209 genSkipc(&rFalseIfx);
5213 if(ifx) ifx->generated = 1;
5217 /* chars are out of the way. now do ints and longs */
5220 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5227 genSkipCond(&rFalseIfx,left,size,7);
5228 if(ifx) ifx->generated = 1;
5233 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5235 //rFalseIfx.condition ^= 1;
5236 //genSkipCond(&rFalseIfx,left,size,7);
5237 //rFalseIfx.condition ^= 1;
5239 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5240 if(rFalseIfx.condition)
5241 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5243 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5245 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5246 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5247 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5250 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5252 if(rFalseIfx.condition) {
5254 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5260 genSkipc(&rFalseIfx);
5261 pic16_emitpLabel(truelbl->key);
5262 if(ifx) ifx->generated = 1;
5269 if( (lit & 0xff) == 0) {
5270 /* lower byte is zero */
5271 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5272 i = ((lit >> 8) & 0xff) ^0x80;
5273 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5274 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5275 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5276 genSkipc(&rFalseIfx);
5279 if(ifx) ifx->generated = 1;
5284 /* Special cases for signed longs */
5285 if( (lit & 0xffffff) == 0) {
5286 /* lower byte is zero */
5287 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5288 i = ((lit >> 8*3) & 0xff) ^0x80;
5289 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5290 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5291 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5292 genSkipc(&rFalseIfx);
5295 if(ifx) ifx->generated = 1;
5303 if(lit & (0x80 << (size*8))) {
5304 /* lit is negative */
5305 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5307 //genSkipCond(&rFalseIfx,left,size,7);
5309 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5311 if(rFalseIfx.condition)
5312 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5314 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5318 /* lit is positive */
5319 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5320 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5321 if(rFalseIfx.condition)
5322 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5324 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5329 This works, but is only good for ints.
5330 It also requires a "known zero" register.
5331 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5332 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5333 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5334 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5335 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5336 genSkipc(&rFalseIfx);
5338 pic16_emitpLabel(truelbl->key);
5339 if(ifx) ifx->generated = 1;
5343 /* There are no more special cases, so perform a general compare */
5345 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5346 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5350 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5352 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5354 //rFalseIfx.condition ^= 1;
5355 genSkipc(&rFalseIfx);
5357 pic16_emitpLabel(truelbl->key);
5359 if(ifx) ifx->generated = 1;
5366 /* sign is out of the way. So now do an unsigned compare */
5367 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5370 /* General case - compare to an unsigned literal on the right.*/
5372 i = (lit >> (size*8)) & 0xff;
5373 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5374 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5376 i = (lit >> (size*8)) & 0xff;
5379 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5381 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5383 /* this byte of the lit is zero,
5384 *if it's not the last then OR in the variable */
5386 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5391 pic16_emitpLabel(lbl->key);
5392 // pic16_emitpLabel(truelbl->key);
5393 //if(emitFinalCheck)
5394 genSkipc(&rFalseIfx);
5396 pic16_emitpLabel(truelbl->key);
5398 if(ifx) ifx->generated = 1;
5405 if(AOP_TYPE(left) == AOP_LIT) {
5406 //symbol *lbl = newiTempLabel(NULL);
5408 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5411 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5414 if((lit == 0) && (sign == 0)){
5417 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5419 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5421 genSkipz2(&rFalseIfx,0);
5422 if(ifx) ifx->generated = 1;
5429 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5430 /* degenerate compare can never be true */
5431 if(rFalseIfx.condition == 0)
5432 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5434 if(ifx) ifx->generated = 1;
5439 /* signed comparisons to a literal byte */
5441 int lp1 = (lit+1) & 0xff;
5443 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5446 rFalseIfx.condition ^= 1;
5447 genSkipCond(&rFalseIfx,right,0,7);
5450 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5451 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5452 genSkipz2(&rFalseIfx,1);
5455 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5456 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5457 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5458 rFalseIfx.condition ^= 1;
5459 genSkipc(&rFalseIfx);
5463 /* unsigned comparisons to a literal byte */
5465 switch(lit & 0xff ) {
5467 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5468 genSkipz2(&rFalseIfx,0);
5471 rFalseIfx.condition ^= 1;
5472 genSkipCond(&rFalseIfx,right,0,7);
5476 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5477 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5478 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5479 rFalseIfx.condition ^= 1;
5480 if (AOP_TYPE(result) == AOP_CRY)
5481 genSkipc(&rFalseIfx);
5483 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5484 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5490 if(ifx) ifx->generated = 1;
5491 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5497 /* Size is greater than 1 */
5505 /* this means lit = 0xffffffff, or -1 */
5508 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5509 rFalseIfx.condition ^= 1;
5510 genSkipCond(&rFalseIfx,right,size,7);
5511 if(ifx) ifx->generated = 1;
5513 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5522 if(rFalseIfx.condition) {
5523 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5524 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5527 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5529 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5533 if(rFalseIfx.condition) {
5534 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5535 pic16_emitpLabel(truelbl->key);
5537 rFalseIfx.condition ^= 1;
5538 genSkipCond(&rFalseIfx,right,s,7);
5541 if(ifx) ifx->generated = 1;
5543 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5549 if((size == 1) && (0 == (lp1&0xff))) {
5550 /* lower byte of signed word is zero */
5551 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5552 i = ((lp1 >> 8) & 0xff) ^0x80;
5553 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5554 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5555 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5557 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5559 if(ifx) ifx->generated = 1;
5562 rFalseIfx.condition ^= 1;
5563 genSkipc(&rFalseIfx);
5564 if(ifx) ifx->generated = 1;
5570 if(lit & (0x80 << (size*8))) {
5571 /* Lit is less than zero */
5572 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5573 //rFalseIfx.condition ^= 1;
5574 //genSkipCond(&rFalseIfx,left,size,7);
5575 //rFalseIfx.condition ^= 1;
5576 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5577 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5579 if(rFalseIfx.condition)
5580 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5582 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5586 /* Lit is greater than or equal to zero */
5587 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5588 //rFalseIfx.condition ^= 1;
5589 //genSkipCond(&rFalseIfx,right,size,7);
5590 //rFalseIfx.condition ^= 1;
5592 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5593 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5595 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5596 if(rFalseIfx.condition)
5597 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5599 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5603 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5604 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5608 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5610 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5612 rFalseIfx.condition ^= 1;
5613 //rFalseIfx.condition = 1;
5614 genSkipc(&rFalseIfx);
5616 pic16_emitpLabel(truelbl->key);
5618 if(ifx) ifx->generated = 1;
5621 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5628 /* compare word or long to an unsigned literal on the right.*/
5633 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5636 break; /* handled above */
5639 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5641 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5642 genSkipz2(&rFalseIfx,0);
5646 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5648 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5651 if(rFalseIfx.condition)
5652 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5654 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5657 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5658 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5660 rFalseIfx.condition ^= 1;
5661 genSkipc(&rFalseIfx);
5664 pic16_emitpLabel(truelbl->key);
5666 if(ifx) ifx->generated = 1;
5668 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5676 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5677 i = (lit >> (size*8)) & 0xff;
5679 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5680 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5683 i = (lit >> (size*8)) & 0xff;
5686 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5688 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5690 /* this byte of the lit is zero,
5691 * if it's not the last then OR in the variable */
5693 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5698 pic16_emitpLabel(lbl->key);
5700 rFalseIfx.condition ^= 1;
5702 genSkipc(&rFalseIfx);
5706 pic16_emitpLabel(truelbl->key);
5707 if(ifx) ifx->generated = 1;
5709 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5715 /* Compare two variables */
5717 DEBUGpic16_emitcode(";sign","%d",sign);
5721 /* Sigh. thus sucks... */
5725 pctemp = pic16_popGetTempReg(1);
5726 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5727 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5728 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5729 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5730 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5731 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5732 pic16_popReleaseTempReg(pctemp, 1);
5734 /* Signed char comparison */
5735 /* Special thanks to Nikolai Golovchenko for this snippet */
5736 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5737 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5738 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5739 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5740 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5741 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5743 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5744 genSkipc(&rFalseIfx);
5746 if(ifx) ifx->generated = 1;
5748 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5756 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5757 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5761 /* The rest of the bytes of a multi-byte compare */
5765 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5768 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5769 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5774 pic16_emitpLabel(lbl->key);
5776 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5777 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5778 (AOP_TYPE(result) == AOP_REG)) {
5779 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5780 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5782 genSkipc(&rFalseIfx);
5784 //genSkipc(&rFalseIfx);
5785 if(ifx) ifx->generated = 1;
5788 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5796 if ((AOP_TYPE(result) != AOP_CRY)
5797 && AOP_SIZE(result)) {
5798 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5800 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5802 pic16_outBitC(result);
5804 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5805 /* if the result is used in the next
5806 ifx conditional branch then generate
5807 code a little differently */
5809 genIfxJump (ifx,"c");
5811 pic16_outBitC(result);
5812 /* leave the result in acc */
5817 #elif 0 /* VR version of genCmp() */ /* } else { */
5819 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5820 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5821 operand *result, int offset, int invert_op)
5825 /* check condition, > or < ?? */
5826 if(rIfx->condition != 0)invert_op ^= 1;
5828 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5830 if(!ifx)invert_op ^= 1;
5832 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5833 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5836 if(!invert_op)return POC_CPFSGT;
5837 else return POC_CPFSLT;
5840 static int compareAopfirstpass=1;
5842 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5843 operand *oper, int offset, operand *result,
5844 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5850 /* invert if there is a result to be loaded, in order to fit,
5851 * SETC/CLRC sequence */
5852 if(AOP_SIZE(result))invert_op ^= 1;
5854 // if(sign && !offset)invert_op ^= 1;
5856 // if(sign)invert_op ^= 1;
5858 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5860 if(AOP_SIZE(result) && compareAopfirstpass) {
5863 pic16_emitpcode(POC_SETF, pcop2);
5868 pic16_emitpcode(POC_CLRF, pcop2);
5874 compareAopfirstpass = 0;
5876 /* there is a bug when comparing operands with size > 1,
5877 * because higher bytes can be equal and test should be performed
5878 * to the next lower byte, current algorithm, considers operands
5879 * inequal in these cases! -- VR 20041107 */
5883 pic16_emitpcode(op, pcop);
5885 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5888 if((!sign || !offset) && AOP_SIZE(result)) {
5891 pic16_emitpcode(POC_CLRF, pcop2);
5896 pic16_emitpcode(POC_SETF, pcop2);
5901 /* don't emit final branch (offset == 0) */
5905 pic16_emitpcode(POC_RRCF, pcop2);
5907 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5910 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5911 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5912 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5914 truelbl = newiTempLabel( NULL );
5915 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5916 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5917 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5919 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5920 pic16_emitpLabel(truelbl->key);
5922 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5927 static void genCmp (operand *left, operand *right,
5928 operand *result, iCode *ifx, int sign)
5932 resolvedIfx rFalseIfx;
5933 symbol *falselbl, *tlbl;
5937 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5939 resolveIfx(&rFalseIfx, ifx);
5940 size = max(AOP_SIZE(left), AOP_SIZE(right));
5942 /* if left & right are bit variables */
5943 if(AOP_TYPE(left) == AOP_CRY
5944 && AOP_TYPE(right) == AOP_CRY ) {
5946 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5947 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5949 werror(W_POSSBUG2, __FILE__, __LINE__);
5953 /* if literal is on the right then swap with left */
5954 if((AOP_TYPE(right) == AOP_LIT)) {
5955 operand *tmp = right ;
5956 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5958 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5960 // lit = (lit - 1) & mask;
5963 rFalseIfx.condition ^= 1; /* reverse compare */
5965 if ((AOP_TYPE(left) == AOP_LIT)) {
5966 /* float compares are handled by support functions */
5967 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5970 /* actual comparing algorithm */
5971 // size = AOP_SIZE( right );
5973 falselbl = newiTempLabel( NULL );
5974 if(AOP_TYPE(left) == AOP_LIT) {
5975 /* compare to literal */
5976 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5979 pCodeOp *pct, *pct2;
5982 /* signed compare */
5983 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5985 pct = pic16_popCopyReg(&pic16_pc_prodl);
5986 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5987 tlbl = newiTempLabel( NULL );
5989 /* first compare signs:
5990 * a. if both are positive, compare just like unsigned
5991 * b. if both are negative, invert cmpop, compare just like unsigned
5992 * c. if different signs, determine the result directly */
5998 tlbl1 = newiTempLabel( NULL );
5999 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6003 /* literal is zero or positive:
6004 * a. if carry is zero, too, continue compare,
6005 * b. if carry is set, then continue depending on cmpop ^ condition:
6006 * 1. '<' return false (literal < variable),
6007 * 2. '>' return true (literal > variable) */
6008 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6009 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6012 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6013 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6017 /* literal is negative:
6018 * a. if carry is set, too, continue compare,
6019 * b. if carry is zero, then continue depending on cmpop ^ condition:
6020 * 1. '<' return true (literal < variable),
6021 * 2. '>' return false (literal > variable) */
6022 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6023 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6025 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6026 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6031 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6033 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6034 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6039 pic16_emitpLabel( tlbl1->key );
6042 compareAopfirstpass=1;
6043 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6044 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6045 // pic16_emitpcode(POC_MOVWF, pct);
6047 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6048 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6049 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6050 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6054 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6055 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6056 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6057 // pic16_emitpcode(POC_MOVWF, pct);
6059 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6060 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6061 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6062 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6063 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6066 if(ifx)ifx->generated = 1;
6068 if(AOP_SIZE(result)) {
6069 pic16_emitpLabel(tlbl->key);
6070 pic16_emitpLabel(falselbl->key);
6071 pic16_outBitOp( result, pct2 );
6073 pic16_emitpLabel(tlbl->key);
6077 /* unsigned compare */
6078 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6080 compareAopfirstpass=1;
6083 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6084 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6087 if(ifx)ifx->generated = 1;
6089 if(AOP_SIZE(result)) {
6090 pic16_emitpLabel(falselbl->key);
6091 pic16_outBitC( result );
6096 /* compare registers */
6097 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6101 pCodeOp *pct, *pct2;
6103 /* signed compare */
6104 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6106 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6107 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6108 tlbl = newiTempLabel( NULL );
6110 compareAopfirstpass=1;
6113 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6114 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6115 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6116 pic16_emitpcode(POC_MOVWF, pct);
6118 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6119 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6120 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6122 /* WREG already holds left + 0x80 */
6123 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6126 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6127 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6128 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6129 pic16_emitpcode(POC_MOVWF, pct);
6131 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6132 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6133 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6135 /* WREG already holds left + 0x80 */
6136 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6137 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6140 if(ifx)ifx->generated = 1;
6142 if(AOP_SIZE(result)) {
6143 pic16_emitpLabel(tlbl->key);
6144 pic16_emitpLabel(falselbl->key);
6145 pic16_outBitOp( result, pct2 );
6147 pic16_emitpLabel(tlbl->key);
6151 /* unsigned compare */
6152 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6154 compareAopfirstpass=1;
6157 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6158 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6162 if(ifx)ifx->generated = 1;
6163 if(AOP_SIZE(result)) {
6165 pic16_emitpLabel(falselbl->key);
6166 pic16_outBitC( result );
6177 /*-----------------------------------------------------------------*/
6178 /* genCmpGt :- greater than comparison */
6179 /*-----------------------------------------------------------------*/
6180 static void genCmpGt (iCode *ic, iCode *ifx)
6182 operand *left, *right, *result;
6183 sym_link *letype , *retype;
6189 right= IC_RIGHT(ic);
6190 result = IC_RESULT(ic);
6192 letype = getSpec(operandType(left));
6193 retype =getSpec(operandType(right));
6194 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6195 /* assign the amsops */
6196 pic16_aopOp (left,ic,FALSE);
6197 pic16_aopOp (right,ic,FALSE);
6198 pic16_aopOp (result,ic,TRUE);
6200 genCmp(right, left, result, ifx, sign);
6202 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6203 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6204 pic16_freeAsmop(result,NULL,ic,TRUE);
6207 /*-----------------------------------------------------------------*/
6208 /* genCmpLt - less than comparisons */
6209 /*-----------------------------------------------------------------*/
6210 static void genCmpLt (iCode *ic, iCode *ifx)
6212 operand *left, *right, *result;
6213 sym_link *letype , *retype;
6219 right= IC_RIGHT(ic);
6220 result = IC_RESULT(ic);
6222 letype = getSpec(operandType(left));
6223 retype =getSpec(operandType(right));
6224 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6226 /* assign the amsops */
6227 pic16_aopOp (left,ic,FALSE);
6228 pic16_aopOp (right,ic,FALSE);
6229 pic16_aopOp (result,ic,TRUE);
6231 genCmp(left, right, result, ifx, sign);
6233 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6234 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6235 pic16_freeAsmop(result,NULL,ic,TRUE);
6240 // FIXME reenable literal optimisation when the pic16 port is stable
6242 /*-----------------------------------------------------------------*/
6243 /* genc16bit2lit - compare a 16 bit value to a literal */
6244 /*-----------------------------------------------------------------*/
6245 static void genc16bit2lit(operand *op, int lit, int offset)
6249 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6250 if( (lit&0xff) == 0)
6255 switch( BYTEofLONG(lit,i)) {
6257 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6260 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6263 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6266 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6267 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6272 switch( BYTEofLONG(lit,i)) {
6274 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6278 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6282 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6285 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6287 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6296 /*-----------------------------------------------------------------*/
6297 /* gencjneshort - compare and jump if not equal */
6298 /*-----------------------------------------------------------------*/
6299 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6301 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6303 int res_offset = 0; /* the result may be a different size then left or right */
6304 int res_size = AOP_SIZE(result);
6306 symbol *lbl, *lbl_done;
6308 unsigned long lit = 0L;
6309 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6311 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6312 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6314 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6315 resolveIfx(&rIfx,ifx);
6316 lbl = newiTempLabel(NULL);
6317 lbl_done = newiTempLabel(NULL);
6320 /* if the left side is a literal or
6321 if the right is in a pointer register and left
6323 if ((AOP_TYPE(left) == AOP_LIT) ||
6324 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6329 if(AOP_TYPE(right) == AOP_LIT)
6330 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6332 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6333 preserve_result = 1;
6335 if(result && !preserve_result)
6338 for(i = 0; i < AOP_SIZE(result); i++)
6339 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6343 /* if the right side is a literal then anything goes */
6344 if (AOP_TYPE(right) == AOP_LIT &&
6345 AOP_TYPE(left) != AOP_DIR ) {
6348 genc16bit2lit(left, lit, 0);
6350 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6353 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6356 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6357 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6359 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6363 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6365 if(res_offset < res_size-1)
6373 /* if the right side is in a register or in direct space or
6374 if the left is a pointer register & right is not */
6375 else if (AOP_TYPE(right) == AOP_REG ||
6376 AOP_TYPE(right) == AOP_DIR ||
6377 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6378 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6379 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6380 int lbl_key = lbl->key;
6383 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6384 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6386 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6387 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6388 __FUNCTION__,__LINE__);
6392 /* switch(size) { */
6394 /* genc16bit2lit(left, lit, 0); */
6396 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6401 if((AOP_TYPE(left) == AOP_DIR) &&
6402 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6404 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6405 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6407 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6409 switch (lit & 0xff) {
6411 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6414 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6415 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6416 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6420 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6421 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6422 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6423 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6427 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6428 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6433 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6436 if(AOP_TYPE(result) == AOP_CRY) {
6437 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6442 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6444 /* fix me. probably need to check result size too */
6445 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6450 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6451 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6458 if(res_offset < res_size-1)
6463 } else if(AOP_TYPE(right) == AOP_REG &&
6464 AOP_TYPE(left) != AOP_DIR){
6467 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6468 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6469 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6474 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6476 if(res_offset < res_size-1)
6481 /* right is a pointer reg need both a & b */
6483 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6485 pic16_emitcode("mov","b,%s",l);
6486 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6487 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6492 if(result && preserve_result)
6495 for(i = 0; i < AOP_SIZE(result); i++)
6496 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6499 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6501 if(result && preserve_result)
6502 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6505 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6507 pic16_emitpLabel(lbl->key);
6509 if(result && preserve_result)
6512 for(i = 0; i < AOP_SIZE(result); i++)
6513 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6515 pic16_emitpLabel(lbl_done->key);
6518 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6526 /*-----------------------------------------------------------------*/
6527 /* gencjne - compare and jump if not equal */
6528 /*-----------------------------------------------------------------*/
6529 static void gencjne(operand *left, operand *right, iCode *ifx)
6531 symbol *tlbl = newiTempLabel(NULL);
6533 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6534 gencjneshort(left, right, lbl);
6536 pic16_emitcode("mov","a,%s",one);
6537 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6538 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6539 pic16_emitcode("clr","a");
6540 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6542 pic16_emitpLabel(lbl->key);
6543 pic16_emitpLabel(tlbl->key);
6549 /*-----------------------------------------------------------------*/
6550 /* is_LitOp - check if operand has to be treated as literal */
6551 /*-----------------------------------------------------------------*/
6552 static bool is_LitOp(operand *op)
6554 return ((AOP_TYPE(op) == AOP_LIT)
6555 || ( (AOP_TYPE(op) == AOP_PCODE)
6556 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6557 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6560 /*-----------------------------------------------------------------*/
6561 /* is_LitAOp - check if operand has to be treated as literal */
6562 /*-----------------------------------------------------------------*/
6563 static bool is_LitAOp(asmop *aop)
6565 return ((aop->type == AOP_LIT)
6566 || ( (aop->type == AOP_PCODE)
6567 && ( (aop->aopu.pcop->type == PO_LITERAL)
6568 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6573 /*-----------------------------------------------------------------*/
6574 /* genCmpEq - generates code for equal to */
6575 /*-----------------------------------------------------------------*/
6576 static void genCmpEq (iCode *ic, iCode *ifx)
6578 operand *left, *right, *result;
6579 symbol *falselbl = newiTempLabel(NULL);
6580 symbol *donelbl = newiTempLabel(NULL);
6582 int preserve_result = 0;
6583 int generate_result = 0;
6585 unsigned long lit = -1;
6589 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6590 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6591 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6593 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6595 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6597 werror(W_POSSBUG2, __FILE__, __LINE__);
6598 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6599 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6603 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6605 operand *tmp = right ;
6610 if (AOP_TYPE(right) == AOP_LIT) {
6611 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6614 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6615 preserve_result = 1;
6617 if(result && AOP_SIZE(result))
6618 generate_result = 1;
6620 if(generate_result && !preserve_result)
6622 for(i = 0; i < AOP_SIZE(result); i++)
6623 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6626 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6627 for(i=0; i < AOP_SIZE(left); i++)
6629 if(AOP_TYPE(left) != AOP_ACC)
6632 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6634 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6636 if(is_LitOp(right)) {
6637 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6638 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6641 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6643 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6648 if(generate_result && preserve_result)
6650 for(i = 0; i < AOP_SIZE(result); i++)
6651 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6655 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6657 if(generate_result && preserve_result)
6658 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6660 if(ifx && IC_TRUE(ifx))
6661 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6663 if(ifx && IC_FALSE(ifx))
6664 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6666 pic16_emitpLabel(falselbl->key);
6670 if(ifx && IC_FALSE(ifx))
6671 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6673 if(generate_result && preserve_result)
6675 for(i = 0; i < AOP_SIZE(result); i++)
6676 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6679 pic16_emitpLabel(donelbl->key);
6685 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6686 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6687 pic16_freeAsmop(result,NULL,ic,TRUE);
6693 // old version kept for reference
6695 /*-----------------------------------------------------------------*/
6696 /* genCmpEq - generates code for equal to */
6697 /*-----------------------------------------------------------------*/
6698 static void genCmpEq (iCode *ic, iCode *ifx)
6700 operand *left, *right, *result;
6701 unsigned long lit = 0L;
6703 symbol *falselbl = newiTempLabel(NULL);
6706 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6709 DEBUGpic16_emitcode ("; ifx is non-null","");
6711 DEBUGpic16_emitcode ("; ifx is null","");
6713 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6714 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6715 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6717 size = max(AOP_SIZE(left),AOP_SIZE(right));
6719 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6721 /* if literal, literal on the right or
6722 if the right is in a pointer register and left
6724 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6725 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6726 operand *tmp = right ;
6732 if(ifx && !AOP_SIZE(result)){
6734 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6735 /* if they are both bit variables */
6736 if (AOP_TYPE(left) == AOP_CRY &&
6737 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6738 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6739 if(AOP_TYPE(right) == AOP_LIT){
6740 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6742 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6743 pic16_emitcode("cpl","c");
6744 } else if(lit == 1L) {
6745 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6747 pic16_emitcode("clr","c");
6749 /* AOP_TYPE(right) == AOP_CRY */
6751 symbol *lbl = newiTempLabel(NULL);
6752 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6753 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6754 pic16_emitcode("cpl","c");
6755 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6757 /* if true label then we jump if condition
6759 tlbl = newiTempLabel(NULL);
6760 if ( IC_TRUE(ifx) ) {
6761 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6762 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6764 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6765 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6767 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6770 /* left and right are both bit variables, result is carry */
6773 resolveIfx(&rIfx,ifx);
6775 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6776 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6777 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6778 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6783 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6785 /* They're not both bit variables. Is the right a literal? */
6786 if(AOP_TYPE(right) == AOP_LIT) {
6787 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6792 switch(lit & 0xff) {
6794 if ( IC_TRUE(ifx) ) {
6795 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6797 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6799 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6800 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6804 if ( IC_TRUE(ifx) ) {
6805 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6807 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6809 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6810 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6814 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6816 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6821 /* end of size == 1 */
6825 genc16bit2lit(left,lit,offset);
6828 /* end of size == 2 */
6833 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6834 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6835 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6836 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6839 /* search for patterns that can be optimized */
6841 genc16bit2lit(left,lit,0);
6845 emitSKPZ; // if hi word unequal
6847 emitSKPNZ; // if hi word equal
6849 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6850 genc16bit2lit(left,lit,2);
6853 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6854 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6858 pic16_emitpLabel(falselbl->key);
6867 } else if(AOP_TYPE(right) == AOP_CRY ) {
6868 /* we know the left is not a bit, but that the right is */
6869 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6870 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6871 pic16_popGet(AOP(right),offset));
6872 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6874 /* if the two are equal, then W will be 0 and the Z bit is set
6875 * we could test Z now, or go ahead and check the high order bytes if
6876 * the variable we're comparing is larger than a byte. */
6879 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6881 if ( IC_TRUE(ifx) ) {
6883 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6884 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6887 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6888 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6892 /* They're both variables that are larger than bits */
6895 tlbl = newiTempLabel(NULL);
6898 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6899 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6901 if ( IC_TRUE(ifx) ) {
6905 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6907 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6908 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6912 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6915 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6916 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6921 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6923 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6924 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6928 if(s>1 && IC_TRUE(ifx)) {
6929 pic16_emitpLabel(tlbl->key);
6930 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6934 /* mark the icode as generated */
6939 /* if they are both bit variables */
6940 if (AOP_TYPE(left) == AOP_CRY &&
6941 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6942 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
6943 if(AOP_TYPE(right) == AOP_LIT){
6944 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6946 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6947 pic16_emitcode("cpl","c");
6948 } else if(lit == 1L) {
6949 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6951 pic16_emitcode("clr","c");
6953 /* AOP_TYPE(right) == AOP_CRY */
6955 symbol *lbl = newiTempLabel(NULL);
6956 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6957 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6958 pic16_emitcode("cpl","c");
6959 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6962 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6963 pic16_outBitC(result);
6967 genIfxJump (ifx,"c");
6970 /* if the result is used in an arithmetic operation
6971 then put the result in place */
6972 pic16_outBitC(result);
6975 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
6976 gencjne(left,right,result,ifx);
6979 gencjne(left,right,newiTempLabel(NULL));
6981 if(IC_TRUE(ifx)->key)
6982 gencjne(left,right,IC_TRUE(ifx)->key);
6984 gencjne(left,right,IC_FALSE(ifx)->key);
6988 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6989 pic16_aopPut(AOP(result),"a",0);
6994 genIfxJump (ifx,"a");
6998 /* if the result is used in an arithmetic operation
6999 then put the result in place */
7001 if (AOP_TYPE(result) != AOP_CRY)
7002 pic16_outAcc(result);
7004 /* leave the result in acc */
7008 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7009 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7010 pic16_freeAsmop(result,NULL,ic,TRUE);
7014 /*-----------------------------------------------------------------*/
7015 /* ifxForOp - returns the icode containing the ifx for operand */
7016 /*-----------------------------------------------------------------*/
7017 static iCode *ifxForOp ( operand *op, iCode *ic )
7021 /* if true symbol then needs to be assigned */
7022 if (IS_TRUE_SYMOP(op))
7025 /* if this has register type condition and
7026 the next instruction is ifx with the same operand
7027 and live to of the operand is upto the ifx only then */
7029 && ic->next->op == IFX
7030 && IC_COND(ic->next)->key == op->key
7031 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7033 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7039 ic->next->op == IFX &&
7040 IC_COND(ic->next)->key == op->key) {
7041 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7046 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7048 ic->next->op == IFX)
7049 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7052 ic->next->op == IFX &&
7053 IC_COND(ic->next)->key == op->key) {
7054 DEBUGpic16_emitcode ("; "," key is okay");
7055 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7056 OP_SYMBOL(op)->liveTo,
7061 /* the code below is completely untested
7062 * it just allows ulong2fs.c compile -- VR */
7065 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7066 __FILE__, __FUNCTION__, __LINE__);
7068 /* if this has register type condition and
7069 the next instruction is ifx with the same operand
7070 and live to of the operand is upto the ifx only then */
7072 ic->next->op == IFX &&
7073 IC_COND(ic->next)->key == op->key &&
7074 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7078 ic->next->op == IFX &&
7079 IC_COND(ic->next)->key == op->key) {
7080 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7084 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7085 __FILE__, __FUNCTION__, __LINE__);
7087 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7092 /*-----------------------------------------------------------------*/
7093 /* genAndOp - for && operation */
7094 /*-----------------------------------------------------------------*/
7095 static void genAndOp (iCode *ic)
7097 operand *left,*right, *result;
7102 /* note here that && operations that are in an
7103 if statement are taken away by backPatchLabels
7104 only those used in arthmetic operations remain */
7105 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7106 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7107 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7109 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7111 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7112 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7113 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7115 /* if both are bit variables */
7116 /* if (AOP_TYPE(left) == AOP_CRY && */
7117 /* AOP_TYPE(right) == AOP_CRY ) { */
7118 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7119 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7120 /* pic16_outBitC(result); */
7122 /* tlbl = newiTempLabel(NULL); */
7123 /* pic16_toBoolean(left); */
7124 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7125 /* pic16_toBoolean(right); */
7126 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7127 /* pic16_outBitAcc(result); */
7130 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7131 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7132 pic16_freeAsmop(result,NULL,ic,TRUE);
7136 /*-----------------------------------------------------------------*/
7137 /* genOrOp - for || operation */
7138 /*-----------------------------------------------------------------*/
7141 modified this code, but it doesn't appear to ever get called
7144 static void genOrOp (iCode *ic)
7146 operand *left,*right, *result;
7151 /* note here that || operations that are in an
7152 if statement are taken away by backPatchLabels
7153 only those used in arthmetic operations remain */
7154 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7155 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7156 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7158 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7160 /* if both are bit variables */
7161 if (AOP_TYPE(left) == AOP_CRY &&
7162 AOP_TYPE(right) == AOP_CRY ) {
7163 pic16_emitcode("clrc","");
7164 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7165 AOP(left)->aopu.aop_dir,
7166 AOP(left)->aopu.aop_dir);
7167 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7168 AOP(right)->aopu.aop_dir,
7169 AOP(right)->aopu.aop_dir);
7170 pic16_emitcode("setc","");
7173 tlbl = newiTempLabel(NULL);
7174 pic16_toBoolean(left);
7176 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7177 pic16_toBoolean(right);
7178 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7180 pic16_outBitAcc(result);
7183 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7184 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7185 pic16_freeAsmop(result,NULL,ic,TRUE);
7188 /*-----------------------------------------------------------------*/
7189 /* isLiteralBit - test if lit == 2^n */
7190 /*-----------------------------------------------------------------*/
7191 static int isLiteralBit(unsigned long lit)
7193 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7194 0x100L,0x200L,0x400L,0x800L,
7195 0x1000L,0x2000L,0x4000L,0x8000L,
7196 0x10000L,0x20000L,0x40000L,0x80000L,
7197 0x100000L,0x200000L,0x400000L,0x800000L,
7198 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7199 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7202 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7203 for(idx = 0; idx < 32; idx++)
7209 /*-----------------------------------------------------------------*/
7210 /* continueIfTrue - */
7211 /*-----------------------------------------------------------------*/
7212 static void continueIfTrue (iCode *ic)
7216 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7220 /*-----------------------------------------------------------------*/
7222 /*-----------------------------------------------------------------*/
7223 static void jumpIfTrue (iCode *ic)
7227 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7231 /*-----------------------------------------------------------------*/
7232 /* jmpTrueOrFalse - */
7233 /*-----------------------------------------------------------------*/
7234 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7236 // ugly but optimized by peephole
7239 symbol *nlbl = newiTempLabel(NULL);
7240 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7241 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7242 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7243 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7245 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7246 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7251 /*-----------------------------------------------------------------*/
7252 /* genAnd - code for and */
7253 /*-----------------------------------------------------------------*/
7254 static void genAnd (iCode *ic, iCode *ifx)
7256 operand *left, *right, *result;
7258 unsigned long lit = 0L;
7264 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7265 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7266 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7268 resolveIfx(&rIfx,ifx);
7270 /* if left is a literal & right is not then exchange them */
7271 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7272 AOP_NEEDSACC(left)) {
7273 operand *tmp = right ;
7278 /* if result = right then exchange them */
7279 if(pic16_sameRegs(AOP(result),AOP(right))){
7280 operand *tmp = right ;
7285 /* if right is bit then exchange them */
7286 if (AOP_TYPE(right) == AOP_CRY &&
7287 AOP_TYPE(left) != AOP_CRY){
7288 operand *tmp = right ;
7292 if(AOP_TYPE(right) == AOP_LIT)
7293 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7295 size = AOP_SIZE(result);
7297 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7300 // result = bit & yy;
7301 if (AOP_TYPE(left) == AOP_CRY){
7302 // c = bit & literal;
7303 if(AOP_TYPE(right) == AOP_LIT){
7305 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7308 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7311 if(size && (AOP_TYPE(result) == AOP_CRY)){
7312 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7315 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7319 pic16_emitcode("clr","c");
7322 if (AOP_TYPE(right) == AOP_CRY){
7324 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7325 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7328 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7330 pic16_emitcode("rrc","a");
7331 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7337 pic16_outBitC(result);
7339 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7340 genIfxJump(ifx, "c");
7344 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7345 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7346 if((AOP_TYPE(right) == AOP_LIT) &&
7347 (AOP_TYPE(result) == AOP_CRY) &&
7348 (AOP_TYPE(left) != AOP_CRY)){
7349 int posbit = isLiteralBit(lit);
7353 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7356 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7362 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7363 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7365 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7366 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7369 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7370 size = AOP_SIZE(left);
7373 int bp = posbit, ofs=0;
7380 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7381 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7385 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7386 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7388 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7395 symbol *tlbl = newiTempLabel(NULL);
7396 int sizel = AOP_SIZE(left);
7402 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7404 /* patch provided by Aaron Colwell */
7405 if((posbit = isLiteralBit(bytelit)) != 0) {
7406 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7407 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7408 (posbit-1),0, PO_GPR_REGISTER));
7410 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7411 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7413 if (bytelit == 0xff) {
7414 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7415 * a peephole could optimize it out -- VR */
7416 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7418 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7419 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7422 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7423 pic16_popGetLabel(tlbl->key));
7427 /* old code, left here for reference -- VR 09/2004 */
7428 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7430 if((posbit = isLiteralBit(bytelit)) != 0)
7431 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7433 if(bytelit != 0x0FFL)
7434 pic16_emitcode("anl","a,%s",
7435 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7436 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7442 // bit = left & literal
7445 pic16_emitpLabel(tlbl->key);
7447 // if(left & literal)
7450 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7453 pic16_emitpLabel(tlbl->key);
7458 pic16_outBitC(result);
7462 /* if left is same as result */
7463 if(pic16_sameRegs(AOP(result),AOP(left))){
7465 for(;size--; offset++,lit>>=8) {
7466 if(AOP_TYPE(right) == AOP_LIT){
7467 switch(lit & 0xff) {
7469 /* and'ing with 0 has clears the result */
7470 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7471 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7474 /* and'ing with 0xff is a nop when the result and left are the same */
7479 int p = pic16_my_powof2( (~lit) & 0xff );
7481 /* only one bit is set in the literal, so use a bcf instruction */
7482 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7483 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7486 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7487 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7488 if(know_W != (lit&0xff))
7489 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7491 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7496 if (AOP_TYPE(left) == AOP_ACC) {
7497 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7499 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7500 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7507 // left & result in different registers
7508 if(AOP_TYPE(result) == AOP_CRY){
7510 // if(size), result in bit
7511 // if(!size && ifx), conditional oper: if(left & right)
7512 symbol *tlbl = newiTempLabel(NULL);
7513 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7515 pic16_emitcode("setb","c");
7517 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7518 pic16_emitcode("anl","a,%s",
7519 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7520 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7525 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7526 pic16_outBitC(result);
7528 jmpTrueOrFalse(ifx, tlbl);
7530 for(;(size--);offset++) {
7532 // result = left & right
7533 if(AOP_TYPE(right) == AOP_LIT){
7534 int t = (lit >> (offset*8)) & 0x0FFL;
7537 pic16_emitcode("clrf","%s",
7538 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7539 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7542 pic16_emitcode("movf","%s,w",
7543 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7544 pic16_emitcode("movwf","%s",
7545 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7546 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7547 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7550 pic16_emitcode("movlw","0x%x",t);
7551 pic16_emitcode("andwf","%s,w",
7552 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7553 pic16_emitcode("movwf","%s",
7554 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7556 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7557 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7558 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7563 if (AOP_TYPE(left) == AOP_ACC) {
7564 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7565 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7567 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7568 pic16_emitcode("andwf","%s,w",
7569 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7570 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7571 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7573 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7574 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7580 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7581 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7582 pic16_freeAsmop(result,NULL,ic,TRUE);
7585 /*-----------------------------------------------------------------*/
7586 /* genOr - code for or */
7587 /*-----------------------------------------------------------------*/
7588 static void genOr (iCode *ic, iCode *ifx)
7590 operand *left, *right, *result;
7592 unsigned long lit = 0L;
7594 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7596 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7597 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7598 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7600 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7602 /* if left is a literal & right is not then exchange them */
7603 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7604 AOP_NEEDSACC(left)) {
7605 operand *tmp = right ;
7610 /* if result = right then exchange them */
7611 if(pic16_sameRegs(AOP(result),AOP(right))){
7612 operand *tmp = right ;
7617 /* if right is bit then exchange them */
7618 if (AOP_TYPE(right) == AOP_CRY &&
7619 AOP_TYPE(left) != AOP_CRY){
7620 operand *tmp = right ;
7625 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7627 if(AOP_TYPE(right) == AOP_LIT)
7628 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7630 size = AOP_SIZE(result);
7634 if (AOP_TYPE(left) == AOP_CRY){
7635 if(AOP_TYPE(right) == AOP_LIT){
7636 // c = bit & literal;
7638 // lit != 0 => result = 1
7639 if(AOP_TYPE(result) == AOP_CRY){
7641 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7642 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7643 // AOP(result)->aopu.aop_dir,
7644 // AOP(result)->aopu.aop_dir);
7646 continueIfTrue(ifx);
7650 // lit == 0 => result = left
7651 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7653 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7656 if (AOP_TYPE(right) == AOP_CRY){
7657 if(pic16_sameRegs(AOP(result),AOP(left))){
7659 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7660 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7661 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7663 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7664 AOP(result)->aopu.aop_dir,
7665 AOP(result)->aopu.aop_dir);
7666 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7667 AOP(right)->aopu.aop_dir,
7668 AOP(right)->aopu.aop_dir);
7669 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7670 AOP(result)->aopu.aop_dir,
7671 AOP(result)->aopu.aop_dir);
7673 if( AOP_TYPE(result) == AOP_ACC) {
7674 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7675 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7676 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7677 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7681 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7682 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7683 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7684 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7686 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7687 AOP(result)->aopu.aop_dir,
7688 AOP(result)->aopu.aop_dir);
7689 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7690 AOP(right)->aopu.aop_dir,
7691 AOP(right)->aopu.aop_dir);
7692 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7693 AOP(left)->aopu.aop_dir,
7694 AOP(left)->aopu.aop_dir);
7695 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7696 AOP(result)->aopu.aop_dir,
7697 AOP(result)->aopu.aop_dir);
7702 symbol *tlbl = newiTempLabel(NULL);
7703 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7706 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7707 if( AOP_TYPE(right) == AOP_ACC) {
7708 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7710 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7711 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7716 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7717 pic16_emitcode(";XXX setb","c");
7718 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7719 AOP(left)->aopu.aop_dir,tlbl->key+100);
7720 pic16_toBoolean(right);
7721 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7722 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7723 jmpTrueOrFalse(ifx, tlbl);
7727 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7734 pic16_outBitC(result);
7736 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7737 genIfxJump(ifx, "c");
7741 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7742 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7743 if((AOP_TYPE(right) == AOP_LIT) &&
7744 (AOP_TYPE(result) == AOP_CRY) &&
7745 (AOP_TYPE(left) != AOP_CRY)){
7747 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7750 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7752 continueIfTrue(ifx);
7755 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7756 // lit = 0, result = boolean(left)
7758 pic16_emitcode(";XXX setb","c");
7759 pic16_toBoolean(right);
7761 symbol *tlbl = newiTempLabel(NULL);
7762 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7764 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7766 genIfxJump (ifx,"a");
7770 pic16_outBitC(result);
7774 /* if left is same as result */
7775 if(pic16_sameRegs(AOP(result),AOP(left))){
7777 for(;size--; offset++,lit>>=8) {
7778 if(AOP_TYPE(right) == AOP_LIT){
7779 if((lit & 0xff) == 0)
7780 /* or'ing with 0 has no effect */
7783 int p = pic16_my_powof2(lit & 0xff);
7785 /* only one bit is set in the literal, so use a bsf instruction */
7786 pic16_emitpcode(POC_BSF,
7787 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7789 if(know_W != (lit & 0xff))
7790 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7791 know_W = lit & 0xff;
7792 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7797 if (AOP_TYPE(left) == AOP_ACC) {
7798 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7799 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7801 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7802 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7804 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7805 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7811 // left & result in different registers
7812 if(AOP_TYPE(result) == AOP_CRY){
7814 // if(size), result in bit
7815 // if(!size && ifx), conditional oper: if(left | right)
7816 symbol *tlbl = newiTempLabel(NULL);
7817 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7818 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7822 pic16_emitcode(";XXX setb","c");
7824 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7825 pic16_emitcode(";XXX orl","a,%s",
7826 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7827 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7832 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7833 pic16_outBitC(result);
7835 jmpTrueOrFalse(ifx, tlbl);
7836 } else for(;(size--);offset++){
7838 // result = left & right
7839 if(AOP_TYPE(right) == AOP_LIT){
7840 int t = (lit >> (offset*8)) & 0x0FFL;
7843 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7844 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7846 pic16_emitcode("movf","%s,w",
7847 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7848 pic16_emitcode("movwf","%s",
7849 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7852 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7853 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7854 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7856 pic16_emitcode("movlw","0x%x",t);
7857 pic16_emitcode("iorwf","%s,w",
7858 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7859 pic16_emitcode("movwf","%s",
7860 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7866 // faster than result <- left, anl result,right
7867 // and better if result is SFR
7868 if (AOP_TYPE(left) == AOP_ACC) {
7869 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7870 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7872 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7873 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7875 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7876 pic16_emitcode("iorwf","%s,w",
7877 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7879 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7880 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7885 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7886 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7887 pic16_freeAsmop(result,NULL,ic,TRUE);
7890 /*-----------------------------------------------------------------*/
7891 /* genXor - code for xclusive or */
7892 /*-----------------------------------------------------------------*/
7893 static void genXor (iCode *ic, iCode *ifx)
7895 operand *left, *right, *result;
7897 unsigned long lit = 0L;
7899 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7901 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7902 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7903 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7905 /* if left is a literal & right is not ||
7906 if left needs acc & right does not */
7907 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7908 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7909 operand *tmp = right ;
7914 /* if result = right then exchange them */
7915 if(pic16_sameRegs(AOP(result),AOP(right))){
7916 operand *tmp = right ;
7921 /* if right is bit then exchange them */
7922 if (AOP_TYPE(right) == AOP_CRY &&
7923 AOP_TYPE(left) != AOP_CRY){
7924 operand *tmp = right ;
7928 if(AOP_TYPE(right) == AOP_LIT)
7929 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7931 size = AOP_SIZE(result);
7935 if (AOP_TYPE(left) == AOP_CRY){
7936 if(AOP_TYPE(right) == AOP_LIT){
7937 // c = bit & literal;
7939 // lit>>1 != 0 => result = 1
7940 if(AOP_TYPE(result) == AOP_CRY){
7942 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
7943 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7945 continueIfTrue(ifx);
7948 pic16_emitcode("setb","c");
7952 // lit == 0, result = left
7953 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7955 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7957 // lit == 1, result = not(left)
7958 if(size && pic16_sameRegs(AOP(result),AOP(left))){
7959 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
7960 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
7961 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7964 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7965 pic16_emitcode("cpl","c");
7972 symbol *tlbl = newiTempLabel(NULL);
7973 if (AOP_TYPE(right) == AOP_CRY){
7975 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7978 int sizer = AOP_SIZE(right);
7980 // if val>>1 != 0, result = 1
7981 pic16_emitcode("setb","c");
7983 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7985 // test the msb of the lsb
7986 pic16_emitcode("anl","a,#0xfe");
7987 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7991 pic16_emitcode("rrc","a");
7993 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7994 pic16_emitcode("cpl","c");
7995 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8000 pic16_outBitC(result);
8002 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8003 genIfxJump(ifx, "c");
8007 if(pic16_sameRegs(AOP(result),AOP(left))){
8008 /* if left is same as result */
8009 for(;size--; offset++) {
8010 if(AOP_TYPE(right) == AOP_LIT){
8011 int t = (lit >> (offset*8)) & 0x0FFL;
8015 if (IS_AOP_PREG(left)) {
8016 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8017 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8018 pic16_aopPut(AOP(result),"a",offset);
8020 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8021 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8022 pic16_emitcode("xrl","%s,%s",
8023 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8024 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8027 if (AOP_TYPE(left) == AOP_ACC)
8028 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8030 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8031 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8033 if (IS_AOP_PREG(left)) {
8034 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8035 pic16_aopPut(AOP(result),"a",offset);
8037 pic16_emitcode("xrl","%s,a",
8038 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8044 // left & result in different registers
8045 if(AOP_TYPE(result) == AOP_CRY){
8047 // if(size), result in bit
8048 // if(!size && ifx), conditional oper: if(left ^ right)
8049 symbol *tlbl = newiTempLabel(NULL);
8050 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8052 pic16_emitcode("setb","c");
8054 if((AOP_TYPE(right) == AOP_LIT) &&
8055 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8056 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8058 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8059 pic16_emitcode("xrl","a,%s",
8060 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8062 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8067 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8068 pic16_outBitC(result);
8070 jmpTrueOrFalse(ifx, tlbl);
8071 } else for(;(size--);offset++){
8073 // result = left & right
8074 if(AOP_TYPE(right) == AOP_LIT){
8075 int t = (lit >> (offset*8)) & 0x0FFL;
8078 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8079 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8080 pic16_emitcode("movf","%s,w",
8081 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8082 pic16_emitcode("movwf","%s",
8083 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8086 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8087 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8088 pic16_emitcode("comf","%s,w",
8089 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8090 pic16_emitcode("movwf","%s",
8091 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8094 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8095 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8096 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8097 pic16_emitcode("movlw","0x%x",t);
8098 pic16_emitcode("xorwf","%s,w",
8099 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8100 pic16_emitcode("movwf","%s",
8101 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8107 // faster than result <- left, anl result,right
8108 // and better if result is SFR
8109 if (AOP_TYPE(left) == AOP_ACC) {
8110 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8111 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8113 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8114 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8115 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8116 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8118 if ( AOP_TYPE(result) != AOP_ACC){
8119 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8120 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8126 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8127 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8128 pic16_freeAsmop(result,NULL,ic,TRUE);
8131 /*-----------------------------------------------------------------*/
8132 /* genInline - write the inline code out */
8133 /*-----------------------------------------------------------------*/
8134 static void genInline (iCode *ic)
8136 char *buffer, *bp, *bp1;
8138 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8140 _G.inLine += (!options.asmpeep);
8142 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8143 strcpy(buffer,IC_INLINE(ic));
8145 while((bp1=strstr(bp, "\\n"))) {
8153 /* This is an experimental code for #pragma inline
8154 and is temporarily disabled for 2.5.0 release */
8162 cbuf = Safe_strdup(buffer);
8163 cblen = strlen(buffer)+1;
8164 memset(cbuf, 0, cblen);
8169 if(*bp != '%')*bp1++ = *bp++;
8175 if(i>elementsInSet(asmInlineMap))break;
8178 s = indexSet(asmInlineMap, i);
8179 DEBUGpc("searching symbol s = `%s'", s);
8180 sym = findSym(SymbolTab, NULL, s);
8183 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8185 strcat(bp1, sym->rname);
8191 if(strlen(bp1) > cblen - 16) {
8192 int i = strlen(cbuf);
8194 cbuf = realloc(cbuf, cblen);
8195 memset(cbuf+i, 0, 50);
8201 buffer = Safe_strdup( cbuf );
8208 /* emit each line as a code */
8214 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8222 /* print label, use this special format with NULL directive
8223 * to denote that the argument should not be indented with tab */
8224 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8231 if ((bp1 != bp) && *bp1)
8232 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8237 _G.inLine -= (!options.asmpeep);
8240 /*-----------------------------------------------------------------*/
8241 /* genRRC - rotate right with carry */
8242 /*-----------------------------------------------------------------*/
8243 static void genRRC (iCode *ic)
8245 operand *left , *result ;
8246 int size, offset = 0, same;
8248 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8250 /* rotate right with carry */
8252 result=IC_RESULT(ic);
8253 pic16_aopOp (left,ic,FALSE);
8254 pic16_aopOp (result,ic,TRUE);
8256 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8258 same = pic16_sameRegs(AOP(result),AOP(left));
8260 size = AOP_SIZE(result);
8262 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8264 /* get the lsb and put it into the carry */
8265 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8272 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8274 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8275 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8281 pic16_freeAsmop(left,NULL,ic,TRUE);
8282 pic16_freeAsmop(result,NULL,ic,TRUE);
8285 /*-----------------------------------------------------------------*/
8286 /* genRLC - generate code for rotate left with carry */
8287 /*-----------------------------------------------------------------*/
8288 static void genRLC (iCode *ic)
8290 operand *left , *result ;
8291 int size, offset = 0;
8294 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8295 /* rotate right with carry */
8297 result=IC_RESULT(ic);
8298 pic16_aopOp (left,ic,FALSE);
8299 pic16_aopOp (result,ic,TRUE);
8301 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8303 same = pic16_sameRegs(AOP(result),AOP(left));
8305 /* move it to the result */
8306 size = AOP_SIZE(result);
8308 /* get the msb and put it into the carry */
8309 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8316 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8318 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8319 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8326 pic16_freeAsmop(left,NULL,ic,TRUE);
8327 pic16_freeAsmop(result,NULL,ic,TRUE);
8331 /* gpasm can get the highest order bit with HIGH/UPPER
8332 * so the following probably is not needed -- VR */
8334 /*-----------------------------------------------------------------*/
8335 /* genGetHbit - generates code get highest order bit */
8336 /*-----------------------------------------------------------------*/
8337 static void genGetHbit (iCode *ic)
8339 operand *left, *result;
8341 result=IC_RESULT(ic);
8342 pic16_aopOp (left,ic,FALSE);
8343 pic16_aopOp (result,ic,FALSE);
8345 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8346 /* get the highest order byte into a */
8347 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8348 if(AOP_TYPE(result) == AOP_CRY){
8349 pic16_emitcode("rlc","a");
8350 pic16_outBitC(result);
8353 pic16_emitcode("rl","a");
8354 pic16_emitcode("anl","a,#0x01");
8355 pic16_outAcc(result);
8359 pic16_freeAsmop(left,NULL,ic,TRUE);
8360 pic16_freeAsmop(result,NULL,ic,TRUE);
8364 /*-----------------------------------------------------------------*/
8365 /* AccRol - rotate left accumulator by known count */
8366 /*-----------------------------------------------------------------*/
8367 static void AccRol (int shCount)
8369 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8370 shCount &= 0x0007; // shCount : 0..7
8375 pic16_emitcode("rl","a");
8378 pic16_emitcode("rl","a");
8379 pic16_emitcode("rl","a");
8382 pic16_emitcode("swap","a");
8383 pic16_emitcode("rr","a");
8386 pic16_emitcode("swap","a");
8389 pic16_emitcode("swap","a");
8390 pic16_emitcode("rl","a");
8393 pic16_emitcode("rr","a");
8394 pic16_emitcode("rr","a");
8397 pic16_emitcode("rr","a");
8403 /*-----------------------------------------------------------------*/
8404 /* AccLsh - left shift accumulator by known count */
8405 /*-----------------------------------------------------------------*/
8406 static void AccLsh (int shCount)
8408 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8414 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8417 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8418 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8421 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8422 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8425 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8428 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8429 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8432 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8433 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8436 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8440 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8443 /*-----------------------------------------------------------------*/
8444 /* AccRsh - right shift accumulator by known count */
8445 /*-----------------------------------------------------------------*/
8446 static void AccRsh (int shCount, int andmask)
8448 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8453 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8456 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8457 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8460 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8461 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8464 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8467 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8468 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8471 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8472 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8475 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8480 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8482 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8486 /*-----------------------------------------------------------------*/
8487 /* AccSRsh - signed right shift accumulator by known count */
8488 /*-----------------------------------------------------------------*/
8489 static void AccSRsh (int shCount)
8492 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8495 pic16_emitcode("mov","c,acc.7");
8496 pic16_emitcode("rrc","a");
8497 } else if(shCount == 2){
8498 pic16_emitcode("mov","c,acc.7");
8499 pic16_emitcode("rrc","a");
8500 pic16_emitcode("mov","c,acc.7");
8501 pic16_emitcode("rrc","a");
8503 tlbl = newiTempLabel(NULL);
8504 /* rotate right accumulator */
8505 AccRol(8 - shCount);
8506 /* and kill the higher order bits */
8507 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8508 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8509 pic16_emitcode("orl","a,#0x%02x",
8510 (unsigned char)~SRMask[shCount]);
8511 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8517 /*-----------------------------------------------------------------*/
8518 /* shiftR1Left2Result - shift right one byte from left to result */
8519 /*-----------------------------------------------------------------*/
8520 static void shiftR1Left2ResultSigned (operand *left, int offl,
8521 operand *result, int offr,
8526 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8528 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8532 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8534 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8536 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8537 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8543 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8545 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8547 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8548 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8550 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8551 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8557 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8559 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8560 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8563 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8564 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8565 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8567 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8568 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8570 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8574 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8575 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8576 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8577 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8578 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8582 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8584 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8585 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8587 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8588 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8589 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8590 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8591 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8596 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8597 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8598 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8599 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8600 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8601 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8603 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8604 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8605 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8606 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8607 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8613 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8614 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8615 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8616 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8618 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8619 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8620 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8628 /*-----------------------------------------------------------------*/
8629 /* shiftR1Left2Result - shift right one byte from left to result */
8630 /*-----------------------------------------------------------------*/
8631 static void shiftR1Left2Result (operand *left, int offl,
8632 operand *result, int offr,
8633 int shCount, int sign)
8637 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8639 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8641 /* Copy the msb into the carry if signed. */
8643 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8653 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8655 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8656 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8662 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8664 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8665 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8668 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8673 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8675 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8676 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8679 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8680 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8681 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8682 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8686 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8687 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8688 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8692 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8693 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8694 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8696 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8701 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8702 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8703 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8704 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8705 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8710 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8711 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8712 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8721 /*-----------------------------------------------------------------*/
8722 /* shiftL1Left2Result - shift left one byte from left to result */
8723 /*-----------------------------------------------------------------*/
8724 static void shiftL1Left2Result (operand *left, int offl,
8725 operand *result, int offr, int shCount)
8730 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8732 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8733 DEBUGpic16_emitcode ("; ***","same = %d",same);
8734 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8736 /* shift left accumulator */
8737 //AccLsh(shCount); // don't comment out just yet...
8738 // pic16_aopPut(AOP(result),"a",offr);
8742 /* Shift left 1 bit position */
8743 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8745 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8747 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8748 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8752 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8753 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8754 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8755 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8758 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8759 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8760 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8761 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8762 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8765 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8766 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8767 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8770 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8771 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8772 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8773 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8776 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8777 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8778 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8779 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8780 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8783 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8784 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8785 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8789 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8794 /*-----------------------------------------------------------------*/
8795 /* movLeft2Result - move byte from left to result */
8796 /*-----------------------------------------------------------------*/
8797 static void movLeft2Result (operand *left, int offl,
8798 operand *result, int offr)
8801 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8802 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8803 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8805 if (*l == '@' && (IS_AOP_PREG(result))) {
8806 pic16_emitcode("mov","a,%s",l);
8807 pic16_aopPut(AOP(result),"a",offr);
8809 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8810 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8815 /*-----------------------------------------------------------------*/
8816 /* shiftL2Left2Result - shift left two bytes from left to result */
8817 /*-----------------------------------------------------------------*/
8818 static void shiftL2Left2Result (operand *left, int offl,
8819 operand *result, int offr, int shCount)
8821 int same = pic16_sameRegs(AOP(result), AOP(left));
8824 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8826 if (same && (offl != offr)) { // shift bytes
8829 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8830 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8832 } else { // just treat as different later on
8845 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8846 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8847 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8851 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8852 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8858 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8859 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8860 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8861 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8862 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8863 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8864 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8866 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8867 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8871 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8872 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8873 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8874 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8875 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8876 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8877 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8878 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8879 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8880 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8883 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8884 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8885 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8886 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8887 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8897 /* note, use a mov/add for the shift since the mov has a
8898 chance of getting optimized out */
8899 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8900 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8901 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8902 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8903 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8907 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8908 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8914 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8915 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8916 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8917 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8918 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8919 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8920 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8921 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8925 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8926 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8930 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8931 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8932 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8933 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8935 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8936 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8937 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8938 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8939 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8940 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8941 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8942 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8945 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8946 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8947 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8948 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8949 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8954 /*-----------------------------------------------------------------*/
8955 /* shiftR2Left2Result - shift right two bytes from left to result */
8956 /*-----------------------------------------------------------------*/
8957 static void shiftR2Left2Result (operand *left, int offl,
8958 operand *result, int offr,
8959 int shCount, int sign)
8961 int same = pic16_sameRegs(AOP(result), AOP(left));
8963 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8965 if (same && (offl != offr)) { // shift right bytes
8968 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8969 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8971 } else { // just treat as different later on
8983 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8988 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8989 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8991 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8992 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8993 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8994 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8999 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9002 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9003 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9010 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9011 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9012 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9014 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9015 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9016 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9017 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9019 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9020 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9021 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9023 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9024 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9025 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9026 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9027 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9031 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9032 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9036 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9037 pic16_emitpcode(POC_BTFSC,
9038 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9039 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9047 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9048 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9050 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9051 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9052 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9053 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9055 pic16_emitpcode(POC_BTFSC,
9056 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9057 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9059 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9060 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9061 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9062 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9064 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9065 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9066 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9067 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9068 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9069 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9070 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9071 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9073 pic16_emitpcode(POC_BTFSC,
9074 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9075 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9077 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9078 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9085 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9086 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9087 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9088 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9091 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9093 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9098 /*-----------------------------------------------------------------*/
9099 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9100 /*-----------------------------------------------------------------*/
9101 static void shiftLLeftOrResult (operand *left, int offl,
9102 operand *result, int offr, int shCount)
9104 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9106 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9107 /* shift left accumulator */
9109 /* or with result */
9110 /* back to result */
9111 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9114 /*-----------------------------------------------------------------*/
9115 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9116 /*-----------------------------------------------------------------*/
9117 static void shiftRLeftOrResult (operand *left, int offl,
9118 operand *result, int offr, int shCount)
9120 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9122 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9123 /* shift right accumulator */
9125 /* or with result */
9126 /* back to result */
9127 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9130 /*-----------------------------------------------------------------*/
9131 /* genlshOne - left shift a one byte quantity by known count */
9132 /*-----------------------------------------------------------------*/
9133 static void genlshOne (operand *result, operand *left, int shCount)
9135 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9136 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9139 /*-----------------------------------------------------------------*/
9140 /* genlshTwo - left shift two bytes by known amount != 0 */
9141 /*-----------------------------------------------------------------*/
9142 static void genlshTwo (operand *result,operand *left, int shCount)
9146 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9147 size = pic16_getDataSize(result);
9149 /* if shCount >= 8 */
9155 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9157 movLeft2Result(left, LSB, result, MSB16);
9159 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9162 /* 1 <= shCount <= 7 */
9165 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9167 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9171 /*-----------------------------------------------------------------*/
9172 /* shiftLLong - shift left one long from left to result */
9173 /* offr = LSB or MSB16 */
9174 /*-----------------------------------------------------------------*/
9175 static void shiftLLong (operand *left, operand *result, int offr )
9177 int size = AOP_SIZE(result);
9178 int same = pic16_sameRegs(AOP(left),AOP(result));
9181 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9183 if (same && (offr == MSB16)) { //shift one byte
9184 for(i=size-1;i>=MSB16;i--) {
9185 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9186 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9189 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9192 if (size > LSB+offr ){
9194 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9196 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9197 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9201 if(size > MSB16+offr){
9203 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9205 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9206 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9210 if(size > MSB24+offr){
9212 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9214 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9215 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9219 if(size > MSB32+offr){
9221 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9223 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9224 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9228 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9232 /*-----------------------------------------------------------------*/
9233 /* genlshFour - shift four byte by a known amount != 0 */
9234 /*-----------------------------------------------------------------*/
9235 static void genlshFour (operand *result, operand *left, int shCount)
9239 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9240 size = AOP_SIZE(result);
9242 /* if shifting more that 3 bytes */
9243 if (shCount >= 24 ) {
9246 /* lowest order of left goes to the highest
9247 order of the destination */
9248 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9250 movLeft2Result(left, LSB, result, MSB32);
9252 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9253 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9254 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9259 /* more than two bytes */
9260 else if ( shCount >= 16 ) {
9261 /* lower order two bytes goes to higher order two bytes */
9263 /* if some more remaining */
9265 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9267 movLeft2Result(left, MSB16, result, MSB32);
9268 movLeft2Result(left, LSB, result, MSB24);
9270 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9271 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9275 /* if more than 1 byte */
9276 else if ( shCount >= 8 ) {
9277 /* lower order three bytes goes to higher order three bytes */
9281 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9283 movLeft2Result(left, LSB, result, MSB16);
9285 else{ /* size = 4 */
9287 movLeft2Result(left, MSB24, result, MSB32);
9288 movLeft2Result(left, MSB16, result, MSB24);
9289 movLeft2Result(left, LSB, result, MSB16);
9290 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9292 else if(shCount == 1)
9293 shiftLLong(left, result, MSB16);
9295 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9296 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9297 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9298 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9303 /* 1 <= shCount <= 7 */
9304 else if(shCount <= 3)
9306 shiftLLong(left, result, LSB);
9307 while(--shCount >= 1)
9308 shiftLLong(result, result, LSB);
9310 /* 3 <= shCount <= 7, optimize */
9312 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9313 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9314 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9318 /*-----------------------------------------------------------------*/
9319 /* genLeftShiftLiteral - left shifting by known count */
9320 /*-----------------------------------------------------------------*/
9321 void pic16_genLeftShiftLiteral (operand *left,
9326 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9330 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9331 pic16_freeAsmop(right,NULL,ic,TRUE);
9333 pic16_aopOp(left,ic,FALSE);
9334 pic16_aopOp(result,ic,TRUE);
9336 size = getSize(operandType(result));
9339 pic16_emitcode("; shift left ","result %d, left %d",size,
9343 /* I suppose that the left size >= result size */
9346 movLeft2Result(left, size, result, size);
9350 else if(shCount >= (size * 8))
9352 pic16_aopPut(AOP(result),zero,size);
9356 genlshOne (result,left,shCount);
9361 genlshTwo (result,left,shCount);
9365 genlshFour (result,left,shCount);
9369 pic16_freeAsmop(left,NULL,ic,TRUE);
9370 pic16_freeAsmop(result,NULL,ic,TRUE);
9373 /*-----------------------------------------------------------------*
9374 * genMultiAsm - repeat assembly instruction for size of register.
9375 * if endian == 1, then the high byte (i.e base address + size of
9376 * register) is used first else the low byte is used first;
9377 *-----------------------------------------------------------------*/
9378 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9383 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9396 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9402 #if !(USE_GENERIC_SIGNED_SHIFT)
9403 /*-----------------------------------------------------------------*/
9404 /* genLeftShift - generates code for left shifting */
9405 /*-----------------------------------------------------------------*/
9406 static void genLeftShift (iCode *ic)
9408 operand *left,*right, *result;
9411 symbol *tlbl , *tlbl1;
9414 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9416 right = IC_RIGHT(ic);
9418 result = IC_RESULT(ic);
9420 pic16_aopOp(right,ic,FALSE);
9422 /* if the shift count is known then do it
9423 as efficiently as possible */
9424 if (AOP_TYPE(right) == AOP_LIT) {
9425 pic16_genLeftShiftLiteral (left,right,result,ic);
9429 /* shift count is unknown then we have to form
9430 * a loop. Get the loop count in WREG : Note: we take
9431 * only the lower order byte since shifting
9432 * more than 32 bits make no sense anyway, ( the
9433 * largest size of an object can be only 32 bits ) */
9435 pic16_aopOp(left,ic,FALSE);
9436 pic16_aopOp(result,ic,FALSE);
9438 /* now move the left to the result if they are not the
9439 * same, and if size > 1,
9440 * and if right is not same to result (!!!) -- VR */
9441 if (!pic16_sameRegs(AOP(left),AOP(result))
9442 && (AOP_SIZE(result) > 1)) {
9444 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9446 size = AOP_SIZE(result);
9451 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9452 if (*l == '@' && (IS_AOP_PREG(result))) {
9454 pic16_emitcode("mov","a,%s",l);
9455 pic16_aopPut(AOP(result),"a",offset);
9459 /* we don't know if left is a literal or a register, take care -- VR */
9460 pic16_mov2f(AOP(result), AOP(left), offset);
9466 size = AOP_SIZE(result);
9468 /* if it is only one byte then */
9470 if(optimized_for_speed) {
9471 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9472 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9473 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9474 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9475 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9476 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9477 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9478 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9479 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9480 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9481 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9482 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9485 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9487 tlbl = newiTempLabel(NULL);
9490 /* this is already done, why change it? */
9491 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9492 pic16_mov2f(AOP(result), AOP(left), 0);
9496 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9497 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9498 pic16_emitpLabel(tlbl->key);
9499 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9500 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9502 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9507 if (pic16_sameRegs(AOP(left),AOP(result))) {
9509 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9511 tlbl = newiTempLabel(NULL);
9512 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9513 genMultiAsm(POC_RRCF, result, size,1);
9514 pic16_emitpLabel(tlbl->key);
9515 genMultiAsm(POC_RLCF, result, size,0);
9516 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9518 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9522 //tlbl = newiTempLabel(NULL);
9524 //tlbl1 = newiTempLabel(NULL);
9526 //reAdjustPreg(AOP(result));
9528 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9529 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9530 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9532 //pic16_emitcode("add","a,acc");
9533 //pic16_aopPut(AOP(result),"a",offset++);
9535 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9537 // pic16_emitcode("rlc","a");
9538 // pic16_aopPut(AOP(result),"a",offset++);
9540 //reAdjustPreg(AOP(result));
9542 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9543 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9546 tlbl = newiTempLabel(NULL);
9547 tlbl1= newiTempLabel(NULL);
9549 size = AOP_SIZE(result);
9552 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9554 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9556 /* offset should be 0, 1 or 3 */
9558 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9560 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9562 pic16_emitpcode(POC_MOVWF, pctemp);
9565 pic16_emitpLabel(tlbl->key);
9568 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9570 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9572 pic16_emitpcode(POC_DECFSZ, pctemp);
9573 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9574 pic16_emitpLabel(tlbl1->key);
9576 pic16_popReleaseTempReg(pctemp,1);
9580 pic16_freeAsmop (right,NULL,ic,TRUE);
9581 pic16_freeAsmop(left,NULL,ic,TRUE);
9582 pic16_freeAsmop(result,NULL,ic,TRUE);
9588 #error old code (left here for reference)
9589 /*-----------------------------------------------------------------*/
9590 /* genLeftShift - generates code for left shifting */
9591 /*-----------------------------------------------------------------*/
9592 static void genLeftShift (iCode *ic)
9594 operand *left,*right, *result;
9597 symbol *tlbl , *tlbl1;
9600 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9602 right = IC_RIGHT(ic);
9604 result = IC_RESULT(ic);
9606 pic16_aopOp(right,ic,FALSE);
9608 /* if the shift count is known then do it
9609 as efficiently as possible */
9610 if (AOP_TYPE(right) == AOP_LIT) {
9611 pic16_genLeftShiftLiteral (left,right,result,ic);
9615 /* shift count is unknown then we have to form
9616 a loop get the loop count in B : Note: we take
9617 only the lower order byte since shifting
9618 more that 32 bits make no sense anyway, ( the
9619 largest size of an object can be only 32 bits ) */
9622 pic16_aopOp(left,ic,FALSE);
9623 pic16_aopOp(result,ic,FALSE);
9625 /* now move the left to the result if they are not the
9627 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9628 AOP_SIZE(result) > 1) {
9630 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9632 size = AOP_SIZE(result);
9635 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9636 if (*l == '@' && (IS_AOP_PREG(result))) {
9638 pic16_emitcode("mov","a,%s",l);
9639 pic16_aopPut(AOP(result),"a",offset);
9642 /* we don't know if left is a literal or a register, take care -- VR */
9643 pic16_mov2f(AOP(result), AOP(left), offset);
9649 size = AOP_SIZE(result);
9651 /* if it is only one byte then */
9653 if(optimized_for_speed) {
9654 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9655 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9656 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9657 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9658 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9659 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9660 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9661 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9662 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9663 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9664 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9665 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9668 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9670 tlbl = newiTempLabel(NULL);
9671 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9672 pic16_mov2f(AOP(result), AOP(left), 0);
9674 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9675 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9678 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9679 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9680 pic16_emitpLabel(tlbl->key);
9681 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9682 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9684 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9689 if (pic16_sameRegs(AOP(left),AOP(result))) {
9691 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9693 tlbl = newiTempLabel(NULL);
9694 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9695 genMultiAsm(POC_RRCF, result, size,1);
9696 pic16_emitpLabel(tlbl->key);
9697 genMultiAsm(POC_RLCF, result, size,0);
9698 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9700 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9704 //tlbl = newiTempLabel(NULL);
9706 //tlbl1 = newiTempLabel(NULL);
9708 //reAdjustPreg(AOP(result));
9710 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9711 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9712 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9714 //pic16_emitcode("add","a,acc");
9715 //pic16_aopPut(AOP(result),"a",offset++);
9717 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9719 // pic16_emitcode("rlc","a");
9720 // pic16_aopPut(AOP(result),"a",offset++);
9722 //reAdjustPreg(AOP(result));
9724 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9725 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9728 tlbl = newiTempLabel(NULL);
9729 tlbl1= newiTempLabel(NULL);
9731 size = AOP_SIZE(result);
9734 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9736 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9738 /* offset should be 0, 1 or 3 */
9740 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9742 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9744 pic16_emitpcode(POC_MOVWF, pctemp);
9747 pic16_emitpLabel(tlbl->key);
9750 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9752 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9754 pic16_emitpcode(POC_DECFSZ, pctemp);
9755 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9756 pic16_emitpLabel(tlbl1->key);
9758 pic16_popReleaseTempReg(pctemp,1);
9762 pic16_freeAsmop (right,NULL,ic,TRUE);
9763 pic16_freeAsmop(left,NULL,ic,TRUE);
9764 pic16_freeAsmop(result,NULL,ic,TRUE);
9768 /*-----------------------------------------------------------------*/
9769 /* genrshOne - right shift a one byte quantity by known count */
9770 /*-----------------------------------------------------------------*/
9771 static void genrshOne (operand *result, operand *left,
9772 int shCount, int sign)
9774 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9775 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9778 /*-----------------------------------------------------------------*/
9779 /* genrshTwo - right shift two bytes by known amount != 0 */
9780 /*-----------------------------------------------------------------*/
9781 static void genrshTwo (operand *result,operand *left,
9782 int shCount, int sign)
9784 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9785 /* if shCount >= 8 */
9789 shiftR1Left2Result(left, MSB16, result, LSB,
9792 movLeft2Result(left, MSB16, result, LSB);
9794 pic16_addSign (result, 1, sign);
9797 /* 1 <= shCount <= 7 */
9799 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9802 /*-----------------------------------------------------------------*/
9803 /* shiftRLong - shift right one long from left to result */
9804 /* offl = LSB or MSB16 */
9805 /*-----------------------------------------------------------------*/
9806 static void shiftRLong (operand *left, int offl,
9807 operand *result, int sign)
9809 int size = AOP_SIZE(result);
9810 int same = pic16_sameRegs(AOP(left),AOP(result));
9812 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9814 if (same && (offl == MSB16)) { //shift one byte right
9815 for(i=MSB16;i<size;i++) {
9816 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9817 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9822 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9828 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9830 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9831 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9835 /* add sign of "a" */
9836 pic16_addSign(result, MSB32, sign);
9840 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9842 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9843 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9847 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9849 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9850 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9854 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9857 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9858 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9863 /*-----------------------------------------------------------------*/
9864 /* genrshFour - shift four byte by a known amount != 0 */
9865 /*-----------------------------------------------------------------*/
9866 static void genrshFour (operand *result, operand *left,
9867 int shCount, int sign)
9869 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9870 /* if shifting more that 3 bytes */
9871 if(shCount >= 24 ) {
9874 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9876 movLeft2Result(left, MSB32, result, LSB);
9878 pic16_addSign(result, MSB16, sign);
9880 else if(shCount >= 16){
9883 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9885 movLeft2Result(left, MSB24, result, LSB);
9886 movLeft2Result(left, MSB32, result, MSB16);
9888 pic16_addSign(result, MSB24, sign);
9890 else if(shCount >= 8){
9893 shiftRLong(left, MSB16, result, sign);
9894 else if(shCount == 0){
9895 movLeft2Result(left, MSB16, result, LSB);
9896 movLeft2Result(left, MSB24, result, MSB16);
9897 movLeft2Result(left, MSB32, result, MSB24);
9898 pic16_addSign(result, MSB32, sign);
9900 else{ //shcount >= 2
9901 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9902 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9903 /* the last shift is signed */
9904 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9905 pic16_addSign(result, MSB32, sign);
9908 else{ /* 1 <= shCount <= 7 */
9910 shiftRLong(left, LSB, result, sign);
9912 shiftRLong(result, LSB, result, sign);
9915 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9916 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9917 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9922 /*-----------------------------------------------------------------*/
9923 /* genRightShiftLiteral - right shifting by known count */
9924 /*-----------------------------------------------------------------*/
9925 static void genRightShiftLiteral (operand *left,
9931 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9934 pic16_freeAsmop(right,NULL,ic,TRUE);
9936 pic16_aopOp(left,ic,FALSE);
9937 pic16_aopOp(result,ic,TRUE);
9939 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9942 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9946 lsize = pic16_getDataSize(left);
9947 res_size = pic16_getDataSize(result);
9948 /* test the LEFT size !!! */
9950 /* I suppose that the left size >= result size */
9952 assert (res_size <= lsize);
9953 while (res_size--) {
9954 pic16_mov2f (AOP(result), AOP(left), res_size);
9958 else if(shCount >= (lsize * 8)){
9961 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9963 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9964 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
9969 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9970 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9971 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9973 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9978 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9985 genrshOne (result,left,shCount,sign);
9989 genrshTwo (result,left,shCount,sign);
9993 genrshFour (result,left,shCount,sign);
10001 pic16_freeAsmop(left,NULL,ic,TRUE);
10002 pic16_freeAsmop(result,NULL,ic,TRUE);
10005 #if !(USE_GENERIC_SIGNED_SHIFT)
10006 /*-----------------------------------------------------------------*/
10007 /* genSignedRightShift - right shift of signed number */
10008 /*-----------------------------------------------------------------*/
10009 static void genSignedRightShift (iCode *ic)
10011 operand *right, *left, *result;
10014 symbol *tlbl, *tlbl1 ;
10017 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10019 /* we do it the hard way put the shift count in b
10020 and loop thru preserving the sign */
10021 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10023 right = IC_RIGHT(ic);
10024 left = IC_LEFT(ic);
10025 result = IC_RESULT(ic);
10027 pic16_aopOp(right,ic,FALSE);
10028 pic16_aopOp(left,ic,FALSE);
10029 pic16_aopOp(result,ic,FALSE);
10032 if ( AOP_TYPE(right) == AOP_LIT) {
10033 genRightShiftLiteral (left,right,result,ic,1);
10036 /* shift count is unknown then we have to form
10037 a loop get the loop count in B : Note: we take
10038 only the lower order byte since shifting
10039 more that 32 bits make no sense anyway, ( the
10040 largest size of an object can be only 32 bits ) */
10042 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10043 //pic16_emitcode("inc","b");
10044 //pic16_freeAsmop (right,NULL,ic,TRUE);
10045 //pic16_aopOp(left,ic,FALSE);
10046 //pic16_aopOp(result,ic,FALSE);
10048 /* now move the left to the result if they are not the
10050 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10051 AOP_SIZE(result) > 1) {
10053 size = AOP_SIZE(result);
10057 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10058 if (*l == '@' && IS_AOP_PREG(result)) {
10060 pic16_emitcode("mov","a,%s",l);
10061 pic16_aopPut(AOP(result),"a",offset);
10063 pic16_aopPut(AOP(result),l,offset);
10065 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10066 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10072 /* mov the highest order bit to OVR */
10073 tlbl = newiTempLabel(NULL);
10074 tlbl1= newiTempLabel(NULL);
10076 size = AOP_SIZE(result);
10079 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10081 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10083 /* offset should be 0, 1 or 3 */
10084 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10086 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10088 pic16_emitpcode(POC_MOVWF, pctemp);
10091 pic16_emitpLabel(tlbl->key);
10093 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10094 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10097 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10100 pic16_emitpcode(POC_DECFSZ, pctemp);
10101 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10102 pic16_emitpLabel(tlbl1->key);
10104 pic16_popReleaseTempReg(pctemp,1);
10106 size = AOP_SIZE(result);
10108 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10109 pic16_emitcode("rlc","a");
10110 pic16_emitcode("mov","ov,c");
10111 /* if it is only one byte then */
10113 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10115 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10116 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10117 pic16_emitcode("mov","c,ov");
10118 pic16_emitcode("rrc","a");
10119 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10120 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10121 pic16_aopPut(AOP(result),"a",0);
10125 reAdjustPreg(AOP(result));
10126 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10127 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10128 pic16_emitcode("mov","c,ov");
10130 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10132 pic16_emitcode("rrc","a");
10133 pic16_aopPut(AOP(result),"a",offset--);
10135 reAdjustPreg(AOP(result));
10136 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10137 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10142 pic16_freeAsmop(left,NULL,ic,TRUE);
10143 pic16_freeAsmop(result,NULL,ic,TRUE);
10144 pic16_freeAsmop(right,NULL,ic,TRUE);
10148 #if !(USE_GENERIC_SIGNED_SHIFT)
10149 #warning This implementation of genRightShift() is incomplete!
10150 /*-----------------------------------------------------------------*/
10151 /* genRightShift - generate code for right shifting */
10152 /*-----------------------------------------------------------------*/
10153 static void genRightShift (iCode *ic)
10155 operand *right, *left, *result;
10159 symbol *tlbl, *tlbl1 ;
10161 /* if signed then we do it the hard way preserve the
10162 sign bit moving it inwards */
10163 letype = getSpec(operandType(IC_LEFT(ic)));
10164 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10166 if (!SPEC_USIGN(letype)) {
10167 genSignedRightShift (ic);
10171 /* signed & unsigned types are treated the same : i.e. the
10172 signed is NOT propagated inwards : quoting from the
10173 ANSI - standard : "for E1 >> E2, is equivalent to division
10174 by 2**E2 if unsigned or if it has a non-negative value,
10175 otherwise the result is implementation defined ", MY definition
10176 is that the sign does not get propagated */
10178 right = IC_RIGHT(ic);
10179 left = IC_LEFT(ic);
10180 result = IC_RESULT(ic);
10182 pic16_aopOp(right,ic,FALSE);
10184 /* if the shift count is known then do it
10185 as efficiently as possible */
10186 if (AOP_TYPE(right) == AOP_LIT) {
10187 genRightShiftLiteral (left,right,result,ic, 0);
10191 /* shift count is unknown then we have to form
10192 a loop get the loop count in B : Note: we take
10193 only the lower order byte since shifting
10194 more that 32 bits make no sense anyway, ( the
10195 largest size of an object can be only 32 bits ) */
10197 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10198 pic16_emitcode("inc","b");
10199 pic16_aopOp(left,ic,FALSE);
10200 pic16_aopOp(result,ic,FALSE);
10202 /* now move the left to the result if they are not the
10204 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10205 AOP_SIZE(result) > 1) {
10207 size = AOP_SIZE(result);
10210 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10211 if (*l == '@' && IS_AOP_PREG(result)) {
10213 pic16_emitcode("mov","a,%s",l);
10214 pic16_aopPut(AOP(result),"a",offset);
10216 pic16_aopPut(AOP(result),l,offset);
10221 tlbl = newiTempLabel(NULL);
10222 tlbl1= newiTempLabel(NULL);
10223 size = AOP_SIZE(result);
10226 /* if it is only one byte then */
10229 tlbl = newiTempLabel(NULL);
10230 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10231 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10232 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10235 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10236 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10237 pic16_emitpLabel(tlbl->key);
10238 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10239 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10241 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10246 reAdjustPreg(AOP(result));
10247 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10248 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10251 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10253 pic16_emitcode("rrc","a");
10254 pic16_aopPut(AOP(result),"a",offset--);
10256 reAdjustPreg(AOP(result));
10258 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10259 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10262 pic16_freeAsmop(left,NULL,ic,TRUE);
10263 pic16_freeAsmop (right,NULL,ic,TRUE);
10264 pic16_freeAsmop(result,NULL,ic,TRUE);
10268 #if (USE_GENERIC_SIGNED_SHIFT)
10269 /*-----------------------------------------------------------------*/
10270 /* genGenericShift - generates code for left or right shifting */
10271 /*-----------------------------------------------------------------*/
10272 static void genGenericShift (iCode *ic, int isShiftLeft) {
10273 operand *left,*right, *result;
10275 int sign, signedCount;
10276 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10277 PIC_OPCODE pos_shift, neg_shift;
10281 right = IC_RIGHT(ic);
10282 left = IC_LEFT(ic);
10283 result = IC_RESULT(ic);
10285 pic16_aopOp(right,ic,FALSE);
10286 pic16_aopOp(left,ic,FALSE);
10287 pic16_aopOp(result,ic,TRUE);
10289 sign = !SPEC_USIGN(operandType (left));
10290 signedCount = !SPEC_USIGN(operandType (right));
10292 /* if the shift count is known then do it
10293 as efficiently as possible */
10294 if (AOP_TYPE(right) == AOP_LIT) {
10295 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10296 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10297 // we should modify right->aopu.aop_lit here!
10298 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10299 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10301 pic16_genLeftShiftLiteral (left,right,result,ic);
10303 genRightShiftLiteral (left,right,result,ic, sign);
10306 } // if (right is literal)
10308 /* shift count is unknown then we have to form a loop.
10309 * Note: we take only the lower order byte since shifting
10310 * more than 32 bits make no sense anyway, ( the
10311 * largest size of an object can be only 32 bits )
10312 * Note: we perform arithmetic shifts if the left operand is
10313 * signed and we do an (effective) right shift, i. e. we
10314 * shift in the sign bit from the left. */
10316 label_complete = newiTempLabel ( NULL );
10317 label_loop_pos = newiTempLabel ( NULL );
10318 label_loop_neg = NULL;
10319 label_negative = NULL;
10320 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10321 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10324 // additional labels needed
10325 label_loop_neg = newiTempLabel ( NULL );
10326 label_negative = newiTempLabel ( NULL );
10329 // copy source to result -- this will effectively truncate the left operand to the size of result!
10330 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10331 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10332 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10333 pic16_mov2f (AOP(result),AOP(left), offset);
10336 // if result is longer than left, fill with zeros (or sign)
10337 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10338 if (sign && AOP_SIZE(left) > 0) {
10339 // shift signed operand -- fill with sign
10340 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10341 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10342 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10343 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10344 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10347 // shift unsigned operand -- fill result with zeros
10348 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10349 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10352 } // if (size mismatch)
10354 pic16_mov2w (AOP(right), 0);
10355 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10356 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10359 // perform a shift by one (shift count is positive)
10360 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10361 // 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])
10362 pic16_emitpLabel (label_loop_pos->key);
10364 if (sign && (pos_shift == POC_RRCF)) {
10365 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10368 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10369 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10370 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10372 // perform a shift by one (shift count is positive)
10373 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10374 // 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])
10375 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10376 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10378 pic16_emitpLabel (label_loop_pos->key);
10379 if (sign && (pos_shift == POC_RRCF)) {
10380 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10383 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10384 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10385 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10386 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10390 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10392 pic16_emitpLabel (label_negative->key);
10393 // perform a shift by -1 (shift count is negative)
10394 // 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)
10396 pic16_emitpLabel (label_loop_neg->key);
10397 if (sign && (neg_shift == POC_RRCF)) {
10398 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10401 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10402 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10403 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10404 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10405 } // if (signedCount)
10407 pic16_emitpLabel (label_complete->key);
10410 pic16_freeAsmop (right,NULL,ic,TRUE);
10411 pic16_freeAsmop(left,NULL,ic,TRUE);
10412 pic16_freeAsmop(result,NULL,ic,TRUE);
10415 static void genLeftShift (iCode *ic) {
10416 genGenericShift (ic, 1);
10419 static void genRightShift (iCode *ic) {
10420 genGenericShift (ic, 0);
10425 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10426 void pic16_loadFSR0(operand *op, int lit)
10428 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10429 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10431 assert (!OP_SYMBOL(op)->remat);
10432 // set up FSR0 with address of result
10433 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10434 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10438 /*----------------------------------------------------------------*/
10439 /* pic16_derefPtr - move one byte from the location ptr points to */
10440 /* to WREG (doWrite == 0) or one byte from WREG */
10441 /* to the location ptr points to (doWrite != 0) */
10442 /*----------------------------------------------------------------*/
10443 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10448 if (!fsr0_setup || !*fsr0_setup)
10450 pic16_loadFSR0( ptr, 0 );
10451 if (fsr0_setup) *fsr0_setup = 1;
10454 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10456 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10460 if (AOP(ptr)->aopu.aop_reg[2]) {
10461 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10462 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10463 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10464 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl)));
10465 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(ptr),2));
10466 pic16_callGenericPointerRW(doWrite, 1);
10468 // data pointer (just 2 byte given)
10469 if (!fsr0_setup || !*fsr0_setup)
10471 pic16_loadFSR0( ptr, 0 );
10472 if (fsr0_setup) *fsr0_setup = 1;
10475 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10477 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10482 assert (0 && "invalid pointer type specified");
10487 /*-----------------------------------------------------------------*/
10488 /* genUnpackBits - generates code for unpacking bits */
10489 /*-----------------------------------------------------------------*/
10490 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10493 sym_link *etype, *letype;
10494 int blen=0, bstr=0;
10497 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10498 etype = getSpec(operandType(result));
10499 letype = getSpec(operandType(left));
10501 // if(IS_BITFIELD(etype)) {
10502 blen = SPEC_BLEN(etype);
10503 bstr = SPEC_BSTR(etype);
10506 lbstr = SPEC_BSTR( letype );
10509 if((blen == 1) && (bstr < 8)) {
10510 /* it is a single bit, so use the appropriate bit instructions */
10511 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10513 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10515 // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10516 if(!IS_PTR(operandType(left))/* && OP_SYMBOL(left)->remat && (ptype == POINTER)*/) {
10517 /* workaround to reduce the extra lfsr instruction */
10518 pic16_emitpcode(POC_BTFSC,
10519 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10521 pic16_loadFSR0 (left, 0);
10522 pic16_emitpcode(POC_BTFSC,
10523 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10526 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10528 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10534 /* the following call to pic16_loadFSR0 is temporary until
10535 * optimization to handle single bit assignments is added
10536 * to the function. Until then use the old safe way! -- VR */
10538 if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
10539 // access symbol directly
10540 pic16_mov2w (AOP(left), 0);
10542 pic16_derefPtr (left, ptype, 0, NULL);
10545 /* if we have bitdisplacement then it fits */
10546 /* into this byte completely or if length is */
10547 /* less than a byte */
10548 if ((shCnt = SPEC_BSTR(etype)) ||
10549 (SPEC_BLEN(etype) <= 8)) {
10551 /* shift right acc */
10554 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10555 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10557 /* VR -- normally I would use the following, but since we use the hack,
10558 * to avoid the masking from AccRsh, why not mask it right now? */
10561 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10564 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10570 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10571 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10578 static void genDataPointerGet(operand *left,
10582 int size, offset = 0, leoffset=0 ;
10584 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10585 pic16_aopOp(result, ic, TRUE);
10589 size = AOP_SIZE(result);
10590 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10594 /* The following tests may save a redudant movff instruction when
10595 * accessing unions */
10597 /* if they are the same */
10598 if (operandsEqu (left, result)) {
10599 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10605 /* if they are the same registers */
10606 if (pic16_sameRegs(AOP(left),AOP(result))) {
10607 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10613 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10614 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10615 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10622 if ( AOP_TYPE(left) == AOP_PCODE) {
10623 fprintf(stderr,"genDataPointerGet %s, %d\n",
10624 AOP(left)->aopu.pcop->name,
10625 (AOP(left)->aopu.pcop->type == PO_DIR)?
10626 PCOR(AOP(left)->aopu.pcop)->instance:
10627 PCOI(AOP(left)->aopu.pcop)->offset);
10631 if(AOP(left)->aopu.pcop->type == PO_DIR)
10632 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10634 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10637 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10639 // pic16_DumpOp("(result)",result);
10640 if(is_LitAOp(AOP(result))) {
10641 pic16_mov2w(AOP(left), offset); // patch 8
10642 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10644 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10645 pic16_popGet(AOP(left), offset), //patch 8
10646 pic16_popGet(AOP(result), offset)));
10654 pic16_freeAsmop(result,NULL,ic,TRUE);
10659 /*-----------------------------------------------------------------*/
10660 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10661 /*-----------------------------------------------------------------*/
10662 static void genNearPointerGet (operand *left,
10666 // asmop *aop = NULL;
10667 //regs *preg = NULL ;
10668 sym_link *rtype, *retype;
10669 sym_link *ltype, *letype;
10673 rtype = operandType(result);
10674 retype= getSpec(rtype);
10675 ltype = operandType(left);
10676 letype= getSpec(ltype);
10678 pic16_aopOp(left,ic,FALSE);
10680 // pic16_DumpOp("(left)",left);
10681 // pic16_DumpOp("(result)",result);
10683 /* if left is rematerialisable and
10684 * result is not bit variable type and
10685 * the left is pointer to data space i.e
10686 * lower 128 bytes of space */
10688 if (AOP_TYPE(left) == AOP_PCODE
10689 && !IS_BITFIELD(retype)
10690 && DCL_TYPE(ltype) == POINTER) {
10692 genDataPointerGet (left,result,ic);
10693 pic16_freeAsmop(left, NULL, ic, TRUE);
10697 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10698 pic16_aopOp (result,ic,TRUE);
10700 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10703 if(IS_BITFIELD( retype )
10704 && (SPEC_BLEN(operandType(result))==1)
10708 int bitstrt, bytestrt;
10710 /* if this is bitfield of size 1, see if we are checking the value
10711 * of a single bit in an if-statement,
10712 * if yes, then don't generate usual code, but execute the
10713 * genIfx directly -- VR */
10717 /* CHECK: if next iCode is IFX
10718 * and current result operand is nextic's conditional operand
10719 * and current result operand live ranges ends at nextic's key number
10721 if((nextic->op == IFX)
10722 && (result == IC_COND(nextic))
10723 && (OP_LIVETO(result) == nextic->seq)
10724 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10726 /* everything is ok then */
10727 /* find a way to optimize the genIfx iCode */
10729 bytestrt = SPEC_BSTR(operandType(result))/8;
10730 bitstrt = SPEC_BSTR(operandType(result))%8;
10732 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10734 genIfxpCOpJump(nextic, jop);
10736 pic16_freeAsmop(left, NULL, ic, TRUE);
10737 pic16_freeAsmop(result, NULL, ic, TRUE);
10743 /* if bitfield then unpack the bits */
10744 if (IS_BITFIELD(letype))
10745 genUnpackBits (result, left, NULL, POINTER);
10747 /* we have can just get the values */
10748 int size = AOP_SIZE(result);
10751 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10753 pic16_loadFSR0( left, 0 );
10757 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10758 pic16_popGet(AOP(result), offset++)));
10760 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10761 pic16_popGet(AOP(result), offset++)));
10767 /* now some housekeeping stuff */
10769 /* we had to allocate for this iCode */
10770 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10771 pic16_freeAsmop(NULL,aop,ic,TRUE);
10773 /* we did not allocate which means left
10774 * already in a pointer register, then
10775 * if size > 0 && this could be used again
10776 * we have to point it back to where it
10778 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10779 if (AOP_SIZE(result) > 1
10780 && !OP_SYMBOL(left)->remat
10781 && ( OP_SYMBOL(left)->liveTo > ic->seq
10783 // int size = AOP_SIZE(result) - 1;
10785 // pic16_emitcode("dec","%s",rname);
10791 pic16_freeAsmop(left,NULL,ic,TRUE);
10792 pic16_freeAsmop(result,NULL,ic,TRUE);
10795 /*-----------------------------------------------------------------*/
10796 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10797 /*-----------------------------------------------------------------*/
10798 static void genPagedPointerGet (operand *left,
10803 regs *preg = NULL ;
10805 sym_link *rtype, *retype;
10807 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10809 rtype = operandType(result);
10810 retype= getSpec(rtype);
10812 pic16_aopOp(left,ic,FALSE);
10814 /* if the value is already in a pointer register
10815 then don't need anything more */
10816 if (!AOP_INPREG(AOP(left))) {
10817 /* otherwise get a free pointer register */
10819 preg = getFreePtr(ic,&aop,FALSE);
10820 pic16_emitcode("mov","%s,%s",
10822 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10823 rname = preg->name ;
10825 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10827 pic16_freeAsmop(left,NULL,ic,TRUE);
10828 pic16_aopOp (result,ic,TRUE);
10830 /* if bitfield then unpack the bits */
10831 if (IS_BITFIELD(retype))
10832 genUnpackBits (result,left,rname,PPOINTER);
10834 /* we have can just get the values */
10835 int size = AOP_SIZE(result);
10840 pic16_emitcode("movx","a,@%s",rname);
10841 pic16_aopPut(AOP(result),"a",offset);
10846 pic16_emitcode("inc","%s",rname);
10850 /* now some housekeeping stuff */
10852 /* we had to allocate for this iCode */
10853 pic16_freeAsmop(NULL,aop,ic,TRUE);
10855 /* we did not allocate which means left
10856 already in a pointer register, then
10857 if size > 0 && this could be used again
10858 we have to point it back to where it
10860 if (AOP_SIZE(result) > 1 &&
10861 !OP_SYMBOL(left)->remat &&
10862 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10864 int size = AOP_SIZE(result) - 1;
10866 pic16_emitcode("dec","%s",rname);
10871 pic16_freeAsmop(result,NULL,ic,TRUE);
10877 /* This code is not adjusted to PIC16 and fails utterly.
10878 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10880 /*-----------------------------------------------------------------*/
10881 /* genFarPointerGet - gget value from far space */
10882 /*-----------------------------------------------------------------*/
10883 static void genFarPointerGet (operand *left,
10884 operand *result, iCode *ic)
10887 sym_link *retype = getSpec(operandType(result));
10889 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10891 pic16_aopOp(left,ic,FALSE);
10893 /* if the operand is already in dptr
10894 then we do nothing else we move the value to dptr */
10895 if (AOP_TYPE(left) != AOP_STR) {
10896 /* if this is remateriazable */
10897 if (AOP_TYPE(left) == AOP_IMMD)
10898 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10899 else { /* we need to get it byte by byte */
10900 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10901 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10902 if (options.model == MODEL_FLAT24)
10904 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10908 /* so dptr know contains the address */
10909 pic16_freeAsmop(left,NULL,ic,TRUE);
10910 pic16_aopOp(result,ic,TRUE);
10912 /* if bit then unpack */
10913 if (IS_BITFIELD(retype))
10914 genUnpackBits(result,left,"dptr",FPOINTER);
10916 size = AOP_SIZE(result);
10920 pic16_emitcode("movx","a,@dptr");
10921 pic16_aopPut(AOP(result),"a",offset++);
10923 pic16_emitcode("inc","dptr");
10927 pic16_freeAsmop(result,NULL,ic,TRUE);
10932 /*-----------------------------------------------------------------*/
10933 /* genCodePointerGet - get value from code space */
10934 /*-----------------------------------------------------------------*/
10935 static void genCodePointerGet (operand *left,
10936 operand *result, iCode *ic)
10939 sym_link *retype = getSpec(operandType(result));
10941 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10943 pic16_aopOp(left,ic,FALSE);
10945 /* if the operand is already in dptr
10946 then we do nothing else we move the value to dptr */
10947 if (AOP_TYPE(left) != AOP_STR) {
10948 /* if this is remateriazable */
10949 if (AOP_TYPE(left) == AOP_IMMD)
10950 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10951 else { /* we need to get it byte by byte */
10952 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10953 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10954 if (options.model == MODEL_FLAT24)
10956 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10960 /* so dptr know contains the address */
10961 pic16_freeAsmop(left,NULL,ic,TRUE);
10962 pic16_aopOp(result,ic,FALSE);
10964 /* if bit then unpack */
10965 if (IS_BITFIELD(retype))
10966 genUnpackBits(result,left,"dptr",CPOINTER);
10968 size = AOP_SIZE(result);
10972 pic16_emitcode("clr","a");
10973 pic16_emitcode("movc","a,@a+dptr");
10974 pic16_aopPut(AOP(result),"a",offset++);
10976 pic16_emitcode("inc","dptr");
10980 pic16_freeAsmop(result,NULL,ic,TRUE);
10985 /*-----------------------------------------------------------------*/
10986 /* genGenPointerGet - gget value from generic pointer space */
10987 /*-----------------------------------------------------------------*/
10988 static void genGenPointerGet (operand *left,
10989 operand *result, iCode *ic)
10991 int size, offset, lit;
10992 sym_link *retype = getSpec(operandType(result));
10994 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10995 pic16_aopOp(left,ic,FALSE);
10996 pic16_aopOp(result,ic,FALSE);
10997 size = AOP_SIZE(result);
10999 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11001 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11003 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11004 // load FSR0 from immediate
11005 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11007 // pic16_loadFSR0( left );
11012 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11014 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11021 else { /* we need to get it byte by byte */
11022 // set up FSR0 with address from left
11023 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11024 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11030 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11032 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11039 /* if bit then unpack */
11040 if (IS_BITFIELD(retype))
11041 genUnpackBits(result,left,"BAD",GPOINTER);
11044 pic16_freeAsmop(left,NULL,ic,TRUE);
11045 pic16_freeAsmop(result,NULL,ic,TRUE);
11051 /*-----------------------------------------------------------------*/
11052 /* genGenPointerGet - gget value from generic pointer space */
11053 /*-----------------------------------------------------------------*/
11054 static void genGenPointerGet (operand *left,
11055 operand *result, iCode *ic)
11057 int size, offset, lit;
11058 sym_link *letype = getSpec(operandType(left));
11060 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11061 pic16_aopOp(left,ic,FALSE);
11062 pic16_aopOp(result,ic,TRUE);
11063 size = AOP_SIZE(result);
11065 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11067 /* if bit then unpack */
11068 if (IS_BITFIELD(letype)) {
11069 genUnpackBits(result,left,"BAD",GPOINTER);
11073 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11075 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11076 // load FSR0 from immediate
11077 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11079 werror(W_POSSBUG2, __FILE__, __LINE__);
11084 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11086 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11093 } else { /* we need to get it byte by byte */
11095 /* set up WREG:PRODL:FSR0L with address from left */
11096 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11097 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11098 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11100 pic16_callGenericPointerRW(0, size);
11102 assignResultValue(result, 1);
11108 pic16_freeAsmop(left,NULL,ic,TRUE);
11109 pic16_freeAsmop(result,NULL,ic,TRUE);
11112 /*-----------------------------------------------------------------*/
11113 /* genConstPointerGet - get value from const generic pointer space */
11114 /*-----------------------------------------------------------------*/
11115 static void genConstPointerGet (operand *left,
11116 operand *result, iCode *ic)
11118 //sym_link *retype = getSpec(operandType(result));
11119 // symbol *albl = newiTempLabel(NULL); // patch 15
11120 // symbol *blbl = newiTempLabel(NULL); //
11121 // PIC_OPCODE poc; // patch 15
11125 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11126 pic16_aopOp(left,ic,FALSE);
11127 pic16_aopOp(result,ic,TRUE);
11128 size = AOP_SIZE(result);
11130 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11132 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11134 // set up table pointer
11135 if( (AOP_TYPE(left) == AOP_PCODE)
11136 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11137 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11139 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11140 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11141 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11142 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11143 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11144 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11146 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11147 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11148 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11152 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11153 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11157 pic16_freeAsmop(left,NULL,ic,TRUE);
11158 pic16_freeAsmop(result,NULL,ic,TRUE);
11162 /*-----------------------------------------------------------------*/
11163 /* genPointerGet - generate code for pointer get */
11164 /*-----------------------------------------------------------------*/
11165 static void genPointerGet (iCode *ic)
11167 operand *left, *result ;
11168 sym_link *type, *etype;
11173 left = IC_LEFT(ic);
11174 result = IC_RESULT(ic) ;
11176 /* depending on the type of pointer we need to
11177 move it to the correct pointer register */
11178 type = operandType(left);
11179 etype = getSpec(type);
11182 if (IS_PTR_CONST(type))
11184 if (IS_CODEPTR(type))
11186 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11188 /* if left is of type of pointer then it is simple */
11189 if (IS_PTR(type) && !IS_FUNC(type->next))
11190 p_type = DCL_TYPE(type);
11192 /* we have to go by the storage class */
11193 p_type = PTR_TYPE(SPEC_OCLS(etype));
11195 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11197 if (SPEC_OCLS(etype)->codesp ) {
11198 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11199 //p_type = CPOINTER ;
11201 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11202 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11203 /*p_type = FPOINTER ;*/
11205 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11206 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11207 /* p_type = PPOINTER; */
11209 if (SPEC_OCLS(etype) == idata ) {
11210 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11211 /* p_type = IPOINTER; */
11213 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11214 /* p_type = POINTER ; */
11218 /* now that we have the pointer type we assign
11219 the pointer values */
11224 genNearPointerGet (left,result,ic);
11228 genPagedPointerGet(left,result,ic);
11232 /* PICs do not support FAR pointers... */
11233 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11235 genFarPointerGet (left,result,ic);
11240 genConstPointerGet (left,result,ic);
11241 //pic16_emitcodePointerGet (left,result,ic);
11246 if (IS_PTR_CONST(type))
11247 genConstPointerGet (left,result,ic);
11250 genGenPointerGet (left,result,ic);
11254 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11255 "genPointerGet: illegal pointer type");
11260 /*-----------------------------------------------------------------*/
11261 /* genPackBits - generates code for packed bit storage */
11262 /*-----------------------------------------------------------------*/
11263 static void genPackBits (sym_link *etype , operand *result,
11265 char *rname, int p_type)
11273 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11274 blen = SPEC_BLEN(etype);
11275 bstr = SPEC_BSTR(etype);
11277 retype = getSpec(operandType(right));
11279 if(AOP_TYPE(right) == AOP_LIT) {
11280 if((blen == 1) && (bstr < 8)) {
11282 /* it is a single bit, so use the appropriate bit instructions */
11284 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11286 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11287 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11288 if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11289 /* workaround to reduce the extra lfsr instruction */
11291 pic16_emitpcode(POC_BSF,
11292 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11294 pic16_emitpcode(POC_BCF,
11295 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11298 pic16_loadFSR0(result, 0);
11300 pic16_emitpcode(POC_BSF,
11301 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11303 pic16_emitpcode(POC_BCF,
11304 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11310 /* move literal to W */
11311 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11314 if(IS_BITFIELD(retype)
11315 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11319 rblen = SPEC_BLEN( retype );
11320 rbstr = SPEC_BSTR( retype );
11323 if(IS_BITFIELD(etype)) {
11324 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11325 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11327 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11330 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11332 if(IS_BITFIELD(etype)) {
11333 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11335 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11338 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11342 /* move right to W */
11343 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11346 /* if the bit length is less than or */
11347 /* it exactly fits a byte then */
11348 if((shCnt=SPEC_BSTR(etype))
11349 || SPEC_BLEN(etype) <= 8 ) {
11350 int fsr0_setup = 0;
11352 if (blen != 8 || bstr != 0) {
11353 // we need to combine the value with the old value
11354 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11356 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11357 SPEC_BSTR(etype), SPEC_BLEN(etype));
11359 /* shift left acc */
11362 /* using PRODH as a temporary register here */
11363 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11365 if (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) {
11366 /* access symbol directly */
11367 pic16_mov2w (AOP(result), 0);
11369 /* get old value */
11370 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11373 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11374 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11375 (unsigned char)(0xff >> (8-bstr))) ));
11376 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11377 } // if (blen != 8 || bstr != 0)
11379 /* write new value back */
11380 if (IS_SYMOP(result) & !IS_PTR(operandType(result))) {
11381 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11383 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11392 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11393 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11398 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11399 rLen = SPEC_BLEN(etype)-8;
11401 /* now generate for lengths greater than one byte */
11405 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11411 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11417 pic16_emitcode("movx","@dptr,a");
11422 DEBUGpic16_emitcode(";lcall","__gptrput");
11430 pic16_mov2w(AOP(right), offset++);
11433 /* last last was not complete */
11435 /* save the byte & read byte */
11438 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11439 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11444 pic16_emitcode ("mov","b,a");
11445 pic16_emitcode("movx","a,@dptr");
11449 pic16_emitcode ("push","b");
11450 pic16_emitcode ("push","acc");
11451 pic16_emitcode ("lcall","__gptrget");
11452 pic16_emitcode ("pop","b");
11458 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11459 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11460 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11461 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11462 // pic16_emitcode ("orl","a,b");
11465 // if (p_type == GPOINTER)
11466 // pic16_emitcode("pop","b");
11471 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11472 // pic16_emitcode("mov","@%s,a",rname);
11476 pic16_emitcode("movx","@dptr,a");
11480 DEBUGpic16_emitcode(";lcall","__gptrput");
11487 // pic16_freeAsmop(right, NULL, ic, TRUE);
11489 /*-----------------------------------------------------------------*/
11490 /* genDataPointerSet - remat pointer to data space */
11491 /*-----------------------------------------------------------------*/
11492 static void genDataPointerSet(operand *right,
11496 int size, offset = 0, resoffset=0 ;
11498 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11499 pic16_aopOp(right,ic,FALSE);
11501 size = AOP_SIZE(right);
11503 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11506 if ( AOP_TYPE(result) == AOP_PCODE) {
11507 fprintf(stderr,"genDataPointerSet %s, %d\n",
11508 AOP(result)->aopu.pcop->name,
11509 (AOP(result)->aopu.pcop->type == PO_DIR)?
11510 PCOR(AOP(result)->aopu.pcop)->instance:
11511 PCOI(AOP(result)->aopu.pcop)->offset);
11515 if(AOP(result)->aopu.pcop->type == PO_DIR)
11516 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11519 if (AOP_TYPE(right) == AOP_LIT) {
11522 if(!IS_FLOAT(operandType( right )))
11523 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11526 unsigned long lit_int;
11530 /* take care if literal is a float */
11531 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11532 lit = info.lit_int;
11535 lit = lit >> (8*offset);
11537 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11538 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11540 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11543 pic16_mov2w(AOP(right), offset);
11544 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11550 pic16_freeAsmop(right,NULL,ic,TRUE);
11555 /*-----------------------------------------------------------------*/
11556 /* genNearPointerSet - pic16_emitcode for near pointer put */
11557 /*-----------------------------------------------------------------*/
11558 static void genNearPointerSet (operand *right,
11564 sym_link *ptype = operandType(result);
11565 sym_link *resetype;
11567 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11568 retype= getSpec(operandType(right));
11569 resetype = getSpec(operandType(result));
11571 pic16_aopOp(result,ic,FALSE);
11573 /* if the result is rematerializable &
11574 * in data space & not a bit variable */
11576 /* and result is not a bit variable */
11577 if (AOP_TYPE(result) == AOP_PCODE
11578 // && AOP_TYPE(result) == AOP_IMMD
11579 && DCL_TYPE(ptype) == POINTER
11580 && !IS_BITFIELD(retype)
11581 && !IS_BITFIELD(resetype)) {
11583 genDataPointerSet (right,result,ic);
11584 pic16_freeAsmop(result,NULL,ic,TRUE);
11588 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11589 pic16_aopOp(right,ic,FALSE);
11590 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11592 /* if bitfield then unpack the bits */
11593 if (IS_BITFIELD(resetype)) {
11594 genPackBits (resetype, result, right, NULL, POINTER);
11596 /* we have can just get the values */
11597 int size = AOP_SIZE(right);
11600 pic16_loadFSR0(result, 0);
11602 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11604 if (AOP_TYPE(right) == AOP_LIT) {
11605 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11607 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11609 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11611 } else { // no literal
11613 pic16_emitpcode(POC_MOVFF,
11614 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11615 pic16_popCopyReg(&pic16_pc_postinc0)));
11617 pic16_emitpcode(POC_MOVFF,
11618 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11619 pic16_popCopyReg(&pic16_pc_indf0)));
11626 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11627 /* now some housekeeping stuff */
11629 /* we had to allocate for this iCode */
11630 pic16_freeAsmop(NULL,aop,ic,TRUE);
11632 /* we did not allocate which means left
11633 * already in a pointer register, then
11634 * if size > 0 && this could be used again
11635 * we have to point it back to where it
11637 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11638 if (AOP_SIZE(right) > 1
11639 && !OP_SYMBOL(result)->remat
11640 && ( OP_SYMBOL(result)->liveTo > ic->seq
11643 int size = AOP_SIZE(right) - 1;
11646 pic16_emitcode("decf","fsr0,f");
11647 //pic16_emitcode("dec","%s",rname);
11651 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11654 pic16_freeAsmop(right,NULL,ic,TRUE);
11655 pic16_freeAsmop(result,NULL,ic,TRUE);
11658 /*-----------------------------------------------------------------*/
11659 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11660 /*-----------------------------------------------------------------*/
11661 static void genPagedPointerSet (operand *right,
11666 regs *preg = NULL ;
11670 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11672 retype= getSpec(operandType(right));
11674 pic16_aopOp(result,ic,FALSE);
11676 /* if the value is already in a pointer register
11677 then don't need anything more */
11678 if (!AOP_INPREG(AOP(result))) {
11679 /* otherwise get a free pointer register */
11681 preg = getFreePtr(ic,&aop,FALSE);
11682 pic16_emitcode("mov","%s,%s",
11684 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11685 rname = preg->name ;
11687 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11689 pic16_freeAsmop(result,NULL,ic,TRUE);
11690 pic16_aopOp (right,ic,FALSE);
11692 /* if bitfield then unpack the bits */
11693 if (IS_BITFIELD(retype))
11694 genPackBits (retype,result,right,rname,PPOINTER);
11696 /* we have can just get the values */
11697 int size = AOP_SIZE(right);
11701 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11704 pic16_emitcode("movx","@%s,a",rname);
11707 pic16_emitcode("inc","%s",rname);
11713 /* now some housekeeping stuff */
11715 /* we had to allocate for this iCode */
11716 pic16_freeAsmop(NULL,aop,ic,TRUE);
11718 /* we did not allocate which means left
11719 already in a pointer register, then
11720 if size > 0 && this could be used again
11721 we have to point it back to where it
11723 if (AOP_SIZE(right) > 1 &&
11724 !OP_SYMBOL(result)->remat &&
11725 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11727 int size = AOP_SIZE(right) - 1;
11729 pic16_emitcode("dec","%s",rname);
11734 pic16_freeAsmop(right,NULL,ic,TRUE);
11740 /* This code is not adjusted to PIC16 and fails utterly...
11741 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11743 /*-----------------------------------------------------------------*/
11744 /* genFarPointerSet - set value from far space */
11745 /*-----------------------------------------------------------------*/
11746 static void genFarPointerSet (operand *right,
11747 operand *result, iCode *ic)
11750 sym_link *retype = getSpec(operandType(right));
11752 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11753 pic16_aopOp(result,ic,FALSE);
11755 /* if the operand is already in dptr
11756 then we do nothing else we move the value to dptr */
11757 if (AOP_TYPE(result) != AOP_STR) {
11758 /* if this is remateriazable */
11759 if (AOP_TYPE(result) == AOP_IMMD)
11760 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11761 else { /* we need to get it byte by byte */
11762 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11763 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11764 if (options.model == MODEL_FLAT24)
11766 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11770 /* so dptr know contains the address */
11771 pic16_freeAsmop(result,NULL,ic,TRUE);
11772 pic16_aopOp(right,ic,FALSE);
11774 /* if bit then unpack */
11775 if (IS_BITFIELD(retype))
11776 genPackBits(retype,result,right,"dptr",FPOINTER);
11778 size = AOP_SIZE(right);
11782 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11784 pic16_emitcode("movx","@dptr,a");
11786 pic16_emitcode("inc","dptr");
11790 pic16_freeAsmop(right,NULL,ic,TRUE);
11794 /*-----------------------------------------------------------------*/
11795 /* genGenPointerSet - set value from generic pointer space */
11796 /*-----------------------------------------------------------------*/
11798 static void genGenPointerSet (operand *right,
11799 operand *result, iCode *ic)
11801 int i, size, offset, lit;
11802 sym_link *retype = getSpec(operandType(right));
11804 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11806 pic16_aopOp(result,ic,FALSE);
11807 pic16_aopOp(right,ic,FALSE);
11808 size = AOP_SIZE(right);
11811 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11813 /* if the operand is already in dptr
11814 then we do nothing else we move the value to dptr */
11815 if (AOP_TYPE(result) != AOP_STR) {
11816 /* if this is remateriazable */
11817 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11818 // WARNING: anythig until "else" is untested!
11819 if (AOP_TYPE(result) == AOP_IMMD) {
11820 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11821 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11822 // load FSR0 from immediate
11823 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11827 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11829 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11835 else { /* we need to get it byte by byte */
11836 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11837 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11839 // set up FSR0 with address of result
11840 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11841 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11843 /* hack hack! see if this the FSR. If so don't load W */
11844 if(AOP_TYPE(right) != AOP_ACC) {
11846 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11848 if(AOP_TYPE(right) == AOP_LIT)
11851 // note: pic16_popGet handles sign extension
11852 for(i=0;i<size;i++) {
11853 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11855 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11857 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11862 for(i=0;i<size;i++) {
11864 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11865 pic16_popCopyReg(&pic16_pc_postinc0)));
11867 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11868 pic16_popCopyReg(&pic16_pc_indf0)));
11874 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11875 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11877 } // if (AOP_TYPE(result) != AOP_IMMD)
11879 } // if (AOP_TYPE(result) != AOP_STR)
11880 /* so dptr know contains the address */
11883 /* if bit then unpack */
11884 if (IS_BITFIELD(retype))
11885 genPackBits(retype,result,right,"dptr",GPOINTER);
11887 size = AOP_SIZE(right);
11890 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11892 // set up FSR0 with address of result
11893 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11894 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11897 if (AOP_TYPE(right) == AOP_LIT) {
11898 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11900 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11902 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11904 } else { // no literal
11906 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11908 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11916 pic16_freeAsmop(right,NULL,ic,TRUE);
11917 pic16_freeAsmop(result,NULL,ic,TRUE);
11921 static void genGenPointerSet (operand *right,
11922 operand *result, iCode *ic)
11925 sym_link *retype = getSpec(operandType(result));
11927 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11929 pic16_aopOp(result,ic,FALSE);
11930 pic16_aopOp(right,ic,FALSE);
11931 size = AOP_SIZE(right);
11933 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11936 /* if bit then unpack */
11937 if (IS_BITFIELD(retype)) {
11938 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11939 genPackBits(retype,result,right,"dptr",GPOINTER);
11943 size = AOP_SIZE(right);
11945 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11948 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11950 /* value of right+0 is placed on stack, which will be retrieved
11951 * by the support function this restoring the stack. The important
11952 * thing is that there is no need to manually restore stack pointer
11954 pushaop(AOP(right), 0);
11955 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11956 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11957 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11958 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
11960 /* load address to write to in WREG:FSR0H:FSR0L */
11961 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
11962 pic16_popCopyReg(&pic16_pc_fsr0l)));
11963 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
11964 pic16_popCopyReg(&pic16_pc_prodl)));
11965 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
11967 pic16_callGenericPointerRW(1, size);
11970 pic16_freeAsmop(right,NULL,ic,TRUE);
11971 pic16_freeAsmop(result,NULL,ic,TRUE);
11974 /*-----------------------------------------------------------------*/
11975 /* genPointerSet - stores the value into a pointer location */
11976 /*-----------------------------------------------------------------*/
11977 static void genPointerSet (iCode *ic)
11979 operand *right, *result ;
11980 sym_link *type, *etype;
11985 right = IC_RIGHT(ic);
11986 result = IC_RESULT(ic) ;
11988 /* depending on the type of pointer we need to
11989 move it to the correct pointer register */
11990 type = operandType(result);
11991 etype = getSpec(type);
11993 /* if left is of type of pointer then it is simple */
11994 if (IS_PTR(type) && !IS_FUNC(type->next)) {
11995 p_type = DCL_TYPE(type);
11998 /* we have to go by the storage class */
11999 p_type = PTR_TYPE(SPEC_OCLS(etype));
12001 /* if (SPEC_OCLS(etype)->codesp ) { */
12002 /* p_type = CPOINTER ; */
12005 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12006 /* p_type = FPOINTER ; */
12008 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12009 /* p_type = PPOINTER ; */
12011 /* if (SPEC_OCLS(etype) == idata ) */
12012 /* p_type = IPOINTER ; */
12014 /* p_type = POINTER ; */
12017 /* now that we have the pointer type we assign
12018 the pointer values */
12023 genNearPointerSet (right,result,ic);
12027 genPagedPointerSet (right,result,ic);
12031 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12033 genFarPointerSet (right,result,ic);
12038 genGenPointerSet (right,result,ic);
12042 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12043 "genPointerSet: illegal pointer type");
12047 /*-----------------------------------------------------------------*/
12048 /* genIfx - generate code for Ifx statement */
12049 /*-----------------------------------------------------------------*/
12050 static void genIfx (iCode *ic, iCode *popIc)
12052 operand *cond = IC_COND(ic);
12057 pic16_aopOp(cond,ic,FALSE);
12059 /* get the value into acc */
12060 if (AOP_TYPE(cond) != AOP_CRY)
12061 pic16_toBoolean(cond);
12064 /* the result is now in the accumulator */
12065 pic16_freeAsmop(cond,NULL,ic,TRUE);
12067 /* if there was something to be popped then do it */
12071 /* if the condition is a bit variable */
12072 if (isbit && IS_ITEMP(cond) &&
12074 genIfxJump(ic,"c");
12075 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12077 if (isbit && !IS_ITEMP(cond))
12078 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12080 genIfxJump(ic,"a");
12085 /*-----------------------------------------------------------------*/
12086 /* genAddrOf - generates code for address of */
12087 /*-----------------------------------------------------------------*/
12088 static void genAddrOf (iCode *ic)
12090 operand *result, *left;
12092 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12093 pCodeOp *pcop0, *pcop1, *pcop2;
12097 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12099 sym = OP_SYMBOL( IC_LEFT(ic) );
12102 /* get address of symbol on stack */
12103 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12105 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12106 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12109 // operands on stack are accessible via "FSR2 + index" with index
12110 // starting at 2 for arguments and growing from 0 downwards for
12111 // local variables (index == 0 is not assigned so we add one here)
12113 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12115 assert (soffs < 0);
12118 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12119 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12120 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12121 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12122 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12123 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12124 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12130 // if(pic16_debug_verbose) {
12131 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12132 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12135 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12136 size = AOP_SIZE(IC_RESULT(ic));
12138 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12139 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12140 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12143 pic16_emitpcode(POC_MOVLW, pcop0);
12144 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12145 pic16_emitpcode(POC_MOVLW, pcop1);
12146 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12147 pic16_emitpcode(POC_MOVLW, pcop2);
12148 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12151 pic16_emitpcode(POC_MOVLW, pcop0);
12152 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12153 pic16_emitpcode(POC_MOVLW, pcop1);
12154 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12156 pic16_emitpcode(POC_MOVLW, pcop0);
12157 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12160 pic16_freeAsmop(left, NULL, ic, FALSE);
12162 pic16_freeAsmop(result,NULL,ic,TRUE);
12167 /*-----------------------------------------------------------------*/
12168 /* genFarFarAssign - assignment when both are in far space */
12169 /*-----------------------------------------------------------------*/
12170 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12172 int size = AOP_SIZE(right);
12175 /* first push the right side on to the stack */
12177 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12179 pic16_emitcode ("push","acc");
12182 pic16_freeAsmop(right,NULL,ic,FALSE);
12183 /* now assign DPTR to result */
12184 pic16_aopOp(result,ic,FALSE);
12185 size = AOP_SIZE(result);
12187 pic16_emitcode ("pop","acc");
12188 pic16_aopPut(AOP(result),"a",--offset);
12190 pic16_freeAsmop(result,NULL,ic,FALSE);
12195 /*-----------------------------------------------------------------*/
12196 /* genAssign - generate code for assignment */
12197 /*-----------------------------------------------------------------*/
12198 static void genAssign (iCode *ic)
12200 operand *result, *right;
12201 int size, offset,know_W;
12202 unsigned long lit = 0L;
12204 result = IC_RESULT(ic);
12205 right = IC_RIGHT(ic) ;
12209 /* if they are the same */
12210 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12213 /* reversed order operands are aopOp'ed so that result operand
12214 * is effective in case right is a stack symbol. This maneauver
12215 * allows to use the _G.resDirect flag later */
12216 pic16_aopOp(result,ic,TRUE);
12217 pic16_aopOp(right,ic,FALSE);
12219 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12221 /* if they are the same registers */
12222 if (pic16_sameRegs(AOP(right),AOP(result)))
12225 /* if the result is a bit */
12226 if (AOP_TYPE(result) == AOP_CRY) {
12227 /* if the right size is a literal then
12228 we know what the value is */
12229 if (AOP_TYPE(right) == AOP_LIT) {
12231 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12232 pic16_popGet(AOP(result),0));
12234 if (((int) operandLitValue(right)))
12235 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12236 AOP(result)->aopu.aop_dir,
12237 AOP(result)->aopu.aop_dir);
12239 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12240 AOP(result)->aopu.aop_dir,
12241 AOP(result)->aopu.aop_dir);
12245 /* the right is also a bit variable */
12246 if (AOP_TYPE(right) == AOP_CRY) {
12247 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12248 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12249 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12251 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12252 AOP(result)->aopu.aop_dir,
12253 AOP(result)->aopu.aop_dir);
12254 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12255 AOP(right)->aopu.aop_dir,
12256 AOP(right)->aopu.aop_dir);
12257 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12258 AOP(result)->aopu.aop_dir,
12259 AOP(result)->aopu.aop_dir);
12263 /* we need to or */
12264 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12265 pic16_toBoolean(right);
12267 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12268 //pic16_aopPut(AOP(result),"a",0);
12272 /* bit variables done */
12274 size = AOP_SIZE(result);
12277 if(AOP_TYPE(right) == AOP_LIT) {
12278 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12279 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12282 unsigned long lit_int;
12287 if(IS_FIXED16X16(operandType(right))) {
12288 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12290 /* take care if literal is a float */
12291 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12292 lit = info.lit_int;
12297 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12298 // sizeof(unsigned long int), sizeof(float));
12301 if (AOP_TYPE(right) == AOP_REG) {
12302 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12304 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12309 /* when do we have to read the program memory?
12310 * - if right itself is a symbol in code space
12311 * (we don't care what it points to if it's a pointer)
12312 * - AND right is not a function (we would want its address)
12314 if(AOP_TYPE(right) != AOP_LIT
12315 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12316 && !IS_FUNC(OP_SYM_TYPE(right))
12317 && !IS_ITEMP(right))
12319 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12320 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12322 // set up table pointer
12323 if(is_LitOp(right)) {
12324 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12325 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12326 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12327 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12328 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12329 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12330 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12332 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12333 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12334 pic16_popCopyReg(&pic16_pc_tblptrl)));
12335 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12336 pic16_popCopyReg(&pic16_pc_tblptrh)));
12337 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12338 pic16_popCopyReg(&pic16_pc_tblptru)));
12341 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12342 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12344 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12345 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12346 pic16_popGet(AOP(result),offset)));
12350 /* FIXME: for pointers we need to extend differently (according
12351 * to pointer type DATA/CODE/EEPROM/... :*/
12352 size = getSize(OP_SYM_TYPE(right));
12353 if(AOP_SIZE(result) > size) {
12354 size = AOP_SIZE(result) - size;
12356 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12366 /* VR - What is this?! */
12367 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12368 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12369 if(aopIdx(AOP(result),0) == 4) {
12371 /* this is a workaround to save value of right into wreg too,
12372 * value of wreg is going to be used later */
12373 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12374 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12375 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12379 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12385 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12386 if(AOP_TYPE(right) == AOP_LIT) {
12388 if(know_W != (lit&0xff))
12389 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12391 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12393 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12397 } else if (AOP_TYPE(right) == AOP_CRY) {
12398 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12400 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12401 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12402 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12404 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12405 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12406 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12408 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12410 if(!_G.resDirect) /* use this aopForSym feature */
12411 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12418 pic16_freeAsmop (right,NULL,ic,FALSE);
12419 pic16_freeAsmop (result,NULL,ic,TRUE);
12422 /*-----------------------------------------------------------------*/
12423 /* genJumpTab - generates code for jump table */
12424 /*-----------------------------------------------------------------*/
12425 static void genJumpTab (iCode *ic)
12430 pCodeOp *jt_offs_hi;
12435 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12436 /* get the condition into accumulator */
12437 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12439 /* multiply by three */
12440 pic16_emitcode("add","a,acc");
12441 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12443 jtab = newiTempLabel(NULL);
12444 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12445 pic16_emitcode("jmp","@a+dptr");
12446 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12449 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12450 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12452 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12453 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12454 pic16_emitpLabel(jtab->key);
12458 jt_offs = pic16_popGetTempReg(0);
12459 jt_offs_hi = pic16_popGetTempReg(1);
12460 jt_label = pic16_popGetLabel (jtab->key);
12461 //fprintf (stderr, "Creating jump table...\n");
12463 // calculate offset into jump table (idx * sizeof (GOTO))
12464 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12465 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12466 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12467 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12468 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12469 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12470 pic16_emitpcode(POC_MOVWF , jt_offs);
12472 // prepare PCLATx (set to first entry in jump table)
12473 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12474 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12475 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12476 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12477 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12479 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12480 pic16_emitpcode(POC_ADDWF , jt_offs);
12481 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12482 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12484 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12486 // release temporaries and prepare jump into table (new PCL --> WREG)
12487 pic16_emitpcode(POC_MOVFW , jt_offs);
12488 pic16_popReleaseTempReg (jt_offs_hi, 1);
12489 pic16_popReleaseTempReg (jt_offs, 0);
12491 // jump into the table
12492 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12494 pic16_emitpLabelFORCE(jtab->key);
12497 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12498 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12500 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12501 /* now generate the jump labels */
12502 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12503 jtab = setNextItem(IC_JTLABELS(ic))) {
12504 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12505 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12508 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12512 /*-----------------------------------------------------------------*/
12513 /* genMixedOperation - gen code for operators between mixed types */
12514 /*-----------------------------------------------------------------*/
12516 TSD - Written for the PIC port - but this unfortunately is buggy.
12517 This routine is good in that it is able to efficiently promote
12518 types to different (larger) sizes. Unfortunately, the temporary
12519 variables that are optimized out by this routine are sometimes
12520 used in other places. So until I know how to really parse the
12521 iCode tree, I'm going to not be using this routine :(.
12523 static int genMixedOperation (iCode *ic)
12526 operand *result = IC_RESULT(ic);
12527 sym_link *ctype = operandType(IC_LEFT(ic));
12528 operand *right = IC_RIGHT(ic);
12534 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12536 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12542 nextright = IC_RIGHT(nextic);
12543 nextleft = IC_LEFT(nextic);
12544 nextresult = IC_RESULT(nextic);
12546 pic16_aopOp(right,ic,FALSE);
12547 pic16_aopOp(result,ic,FALSE);
12548 pic16_aopOp(nextright, nextic, FALSE);
12549 pic16_aopOp(nextleft, nextic, FALSE);
12550 pic16_aopOp(nextresult, nextic, FALSE);
12552 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12554 operand *t = right;
12558 pic16_emitcode(";remove right +","");
12560 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12562 operand *t = right;
12566 pic16_emitcode(";remove left +","");
12570 big = AOP_SIZE(nextleft);
12571 small = AOP_SIZE(nextright);
12573 switch(nextic->op) {
12576 pic16_emitcode(";optimize a +","");
12577 /* if unsigned or not an integral type */
12578 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12579 pic16_emitcode(";add a bit to something","");
12582 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12584 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12585 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12586 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12588 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12596 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12597 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12598 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12601 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12603 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12604 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12605 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12606 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12607 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12610 pic16_emitcode("rlf","known_zero,w");
12617 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12618 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12619 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12621 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12631 pic16_freeAsmop(right,NULL,ic,TRUE);
12632 pic16_freeAsmop(result,NULL,ic,TRUE);
12633 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12634 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12636 nextic->generated = 1;
12643 /*-----------------------------------------------------------------*/
12644 /* genCast - gen code for casting */
12645 /*-----------------------------------------------------------------*/
12646 static void genCast (iCode *ic)
12648 operand *result = IC_RESULT(ic);
12649 sym_link *ctype = operandType(IC_LEFT(ic));
12650 sym_link *rtype = operandType(IC_RIGHT(ic));
12651 sym_link *restype = operandType(IC_RESULT(ic));
12652 operand *right = IC_RIGHT(ic);
12658 /* if they are equivalent then do nothing */
12659 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12662 pic16_aopOp(result,ic,FALSE);
12663 pic16_aopOp(right,ic,FALSE) ;
12665 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12668 /* if the result is a bit */
12669 if (AOP_TYPE(result) == AOP_CRY) {
12671 /* if the right size is a literal then
12672 * we know what the value is */
12673 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12675 if (AOP_TYPE(right) == AOP_LIT) {
12676 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12677 pic16_popGet(AOP(result),0));
12679 if (((int) operandLitValue(right)))
12680 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12681 AOP(result)->aopu.aop_dir,
12682 AOP(result)->aopu.aop_dir);
12684 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12685 AOP(result)->aopu.aop_dir,
12686 AOP(result)->aopu.aop_dir);
12690 /* the right is also a bit variable */
12691 if (AOP_TYPE(right) == AOP_CRY) {
12693 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12695 pic16_emitcode("clrc","");
12696 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12697 AOP(right)->aopu.aop_dir,
12698 AOP(right)->aopu.aop_dir);
12699 pic16_aopPut(AOP(result),"c",0);
12703 /* we need to or */
12704 if (AOP_TYPE(right) == AOP_REG) {
12705 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12706 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12707 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12709 pic16_toBoolean(right);
12710 pic16_aopPut(AOP(result),"a",0);
12714 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12717 size = AOP_SIZE(result);
12719 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12721 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12722 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12723 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12726 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12731 if(IS_BITFIELD(getSpec(restype))
12732 && IS_BITFIELD(getSpec(rtype))) {
12733 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12736 /* if they are the same size : or less */
12737 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12739 /* if they are in the same place */
12740 if (pic16_sameRegs(AOP(right),AOP(result)))
12743 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12745 if (IS_PTR_CONST(rtype))
12747 if (IS_CODEPTR(rtype))
12749 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12752 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12754 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12756 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12759 if(AOP_TYPE(right) == AOP_IMMD) {
12760 pCodeOp *pcop0, *pcop1, *pcop2;
12761 symbol *sym = OP_SYMBOL( right );
12763 size = AOP_SIZE(result);
12765 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12767 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12769 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12772 pic16_emitpcode(POC_MOVLW, pcop0);
12773 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12774 pic16_emitpcode(POC_MOVLW, pcop1);
12775 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12776 pic16_emitpcode(POC_MOVLW, pcop2);
12777 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12780 pic16_emitpcode(POC_MOVLW, pcop0);
12781 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12782 pic16_emitpcode(POC_MOVLW, pcop1);
12783 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12785 pic16_emitpcode(POC_MOVLW, pcop0);
12786 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12790 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12791 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12792 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12793 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12794 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12795 if(AOP_SIZE(result) <2)
12796 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12798 /* if they in different places then copy */
12799 size = AOP_SIZE(result);
12802 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12803 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12810 /* if the result is of type pointer */
12811 if (IS_PTR(ctype)) {
12813 sym_link *type = operandType(right);
12814 sym_link *etype = getSpec(type);
12816 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12818 /* pointer to generic pointer */
12819 if (IS_GENPTR(ctype)) {
12823 p_type = DCL_TYPE(type);
12825 /* we have to go by the storage class */
12826 p_type = PTR_TYPE(SPEC_OCLS(etype));
12828 /* if (SPEC_OCLS(etype)->codesp ) */
12829 /* p_type = CPOINTER ; */
12831 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12832 /* p_type = FPOINTER ; */
12834 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12835 /* p_type = PPOINTER; */
12837 /* if (SPEC_OCLS(etype) == idata ) */
12838 /* p_type = IPOINTER ; */
12840 /* p_type = POINTER ; */
12843 /* the first two bytes are known */
12844 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
12845 size = GPTRSIZE - 1;
12848 if(offset < AOP_SIZE(right)) {
12849 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12850 pic16_mov2f(AOP(result), AOP(right), offset);
12852 if ((AOP_TYPE(right) == AOP_PCODE) &&
12853 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12854 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12855 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12858 pic16_aopPut(AOP(result),
12859 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12864 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12867 /* the last byte depending on type */
12871 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12872 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12873 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12877 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12881 pic16_emitcode(";BUG!? ","%d",__LINE__);
12885 pic16_emitcode(";BUG!? ","%d",__LINE__);
12890 if (GPTRSIZE > AOP_SIZE(right)) {
12891 // assume data pointer... THIS MIGHT BE WRONG!
12892 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12893 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12895 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12900 /* this should never happen */
12901 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12902 "got unknown pointer type");
12905 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
12911 /* just copy the pointers */
12912 size = AOP_SIZE(result);
12915 pic16_aopPut(AOP(result),
12916 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12925 /* so we now know that the size of destination is greater
12926 than the size of the source.
12927 Now, if the next iCode is an operator then we might be
12928 able to optimize the operation without performing a cast.
12930 if(genMixedOperation(ic))
12933 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12935 /* we move to result for the size of source */
12936 size = AOP_SIZE(right);
12941 pic16_mov2f(AOP(result), AOP(right), offset);
12945 /* now depending on the sign of the destination */
12946 size = AOP_SIZE(result) - AOP_SIZE(right);
12947 /* if unsigned or not an integral type */
12948 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
12950 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12952 /* we need to extend the sign :( */
12955 /* Save one instruction of casting char to int */
12956 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12957 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12958 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
12960 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
12963 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12965 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12967 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
12970 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
12975 pic16_freeAsmop(right,NULL,ic,TRUE);
12976 pic16_freeAsmop(result,NULL,ic,TRUE);
12980 /*-----------------------------------------------------------------*/
12981 /* genDjnz - generate decrement & jump if not zero instrucion */
12982 /*-----------------------------------------------------------------*/
12983 static int genDjnz (iCode *ic, iCode *ifx)
12985 symbol *lbl, *lbl1;
12986 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12991 /* if the if condition has a false label
12992 then we cannot save */
12996 /* if the minus is not of the form
12998 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
12999 !IS_OP_LITERAL(IC_RIGHT(ic)))
13002 if (operandLitValue(IC_RIGHT(ic)) != 1)
13005 /* if the size of this greater than one then no
13007 if (getSize(operandType(IC_RESULT(ic))) > 1)
13010 /* otherwise we can save BIG */
13011 lbl = newiTempLabel(NULL);
13012 lbl1= newiTempLabel(NULL);
13014 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13016 if (IS_AOP_PREG(IC_RESULT(ic))) {
13017 pic16_emitcode("dec","%s",
13018 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13019 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13020 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13024 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13025 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13027 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13028 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13032 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13033 ifx->generated = 1;
13037 /*-----------------------------------------------------------------*/
13038 /* genReceive - generate code for a receive iCode */
13039 /*-----------------------------------------------------------------*/
13040 static void genReceive (iCode *ic)
13046 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13047 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13049 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13051 if (isOperandInFarSpace(IC_RESULT(ic))
13052 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13053 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13055 int size = getSize(operandType(IC_RESULT(ic)));
13056 int offset = pic16_fReturnSizePic - size;
13060 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13061 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13065 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13067 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13068 size = AOP_SIZE(IC_RESULT(ic));
13071 pic16_emitcode ("pop","acc");
13072 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13075 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13077 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13080 /* set pseudo stack pointer to where it should be - dw*/
13081 GpsuedoStkPtr = ic->parmBytes;
13083 /* setting GpsuedoStkPtr has side effects here: */
13084 assignResultValue(IC_RESULT(ic), 0);
13087 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13090 /*-----------------------------------------------------------------*/
13091 /* genDummyRead - generate code for dummy read of volatiles */
13092 /*-----------------------------------------------------------------*/
13094 genDummyRead (iCode * ic)
13100 if (op && IS_SYMOP(op)) {
13101 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13102 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13105 pic16_aopOp (op, ic, FALSE);
13106 for (i=0; i < AOP_SIZE(op); i++) {
13107 // may need to protect this from the peepholer -- this is not nice but works...
13108 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13109 pic16_mov2w (AOP(op),i);
13110 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13112 pic16_freeAsmop (op, NULL, ic, TRUE);
13114 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13118 /*-----------------------------------------------------------------*/
13119 /* genpic16Code - generate code for pic16 based controllers */
13120 /*-----------------------------------------------------------------*/
13122 * At this point, ralloc.c has gone through the iCode and attempted
13123 * to optimize in a way suitable for a PIC. Now we've got to generate
13124 * PIC instructions that correspond to the iCode.
13126 * Once the instructions are generated, we'll pass through both the
13127 * peep hole optimizer and the pCode optimizer.
13128 *-----------------------------------------------------------------*/
13130 void genpic16Code (iCode *lic)
13135 lineHead = lineCurr = NULL;
13137 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13138 pic16_addpBlock(pb);
13141 /* if debug information required */
13142 if (options.debug && currFunc) {
13144 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13149 for (ic = lic ; ic ; ic = ic->next ) {
13151 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13152 if ( cln != ic->lineno ) {
13153 if ( options.debug ) {
13154 debugFile->writeCLine (ic);
13157 if(!options.noCcodeInAsm) {
13158 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13159 printCLine(ic->filename, ic->lineno)));
13165 if(options.iCodeInAsm) {
13168 /* insert here code to print iCode as comment */
13169 l = Safe_strdup(printILine(ic));
13170 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13173 /* if the result is marked as
13174 * spilt and rematerializable or code for
13175 * this has already been generated then
13177 if (resultRemat(ic) || ic->generated )
13180 /* depending on the operation */
13199 /* IPOP happens only when trying to restore a
13200 * spilt live range, if there is an ifx statement
13201 * following this pop then the if statement might
13202 * be using some of the registers being popped which
13203 * would destroy the contents of the register so
13204 * we need to check for this condition and handle it */
13206 && ic->next->op == IFX
13207 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13208 genIfx (ic->next,ic);
13226 genEndFunction (ic);
13242 pic16_genPlus (ic) ;
13246 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13247 pic16_genMinus (ic);
13263 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13267 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13273 /* note these two are xlated by algebraic equivalence
13274 * during parsing SDCC.y */
13275 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13276 "got '>=' or '<=' shouldn't have come here");
13280 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13292 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13296 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13300 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13324 genRightShift (ic);
13327 case GET_VALUE_AT_ADDRESS:
13332 if (POINTER_SET(ic))
13359 addSet(&_G.sendSet,ic);
13362 case DUMMY_READ_VOLATILE:
13372 /* now we are ready to call the
13373 peep hole optimizer */
13374 if (!options.nopeep)
13375 peepHole (&lineHead);
13377 /* now do the actual printing */
13378 printLine (lineHead, codeOutFile);
13381 DFPRINTF((stderr,"printing pBlock\n\n"));
13382 pic16_printpBlock(stdout,pb);