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
8227 /* advance to end of line (prevent splitting of comments at ':' */
8228 while (*bp && *bp != '\n') {
8236 if ((bp1 != bp) && *bp1)
8237 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8242 _G.inLine -= (!options.asmpeep);
8245 /*-----------------------------------------------------------------*/
8246 /* genRRC - rotate right with carry */
8247 /*-----------------------------------------------------------------*/
8248 static void genRRC (iCode *ic)
8250 operand *left , *result ;
8251 int size, offset = 0, same;
8253 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8255 /* rotate right with carry */
8257 result=IC_RESULT(ic);
8258 pic16_aopOp (left,ic,FALSE);
8259 pic16_aopOp (result,ic,TRUE);
8261 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8263 same = pic16_sameRegs(AOP(result),AOP(left));
8265 size = AOP_SIZE(result);
8267 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8269 /* get the lsb and put it into the carry */
8270 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8277 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8279 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8280 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8286 pic16_freeAsmop(left,NULL,ic,TRUE);
8287 pic16_freeAsmop(result,NULL,ic,TRUE);
8290 /*-----------------------------------------------------------------*/
8291 /* genRLC - generate code for rotate left with carry */
8292 /*-----------------------------------------------------------------*/
8293 static void genRLC (iCode *ic)
8295 operand *left , *result ;
8296 int size, offset = 0;
8299 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8300 /* rotate right with carry */
8302 result=IC_RESULT(ic);
8303 pic16_aopOp (left,ic,FALSE);
8304 pic16_aopOp (result,ic,TRUE);
8306 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8308 same = pic16_sameRegs(AOP(result),AOP(left));
8310 /* move it to the result */
8311 size = AOP_SIZE(result);
8313 /* get the msb and put it into the carry */
8314 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8321 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8323 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8324 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8331 pic16_freeAsmop(left,NULL,ic,TRUE);
8332 pic16_freeAsmop(result,NULL,ic,TRUE);
8336 /* gpasm can get the highest order bit with HIGH/UPPER
8337 * so the following probably is not needed -- VR */
8339 /*-----------------------------------------------------------------*/
8340 /* genGetHbit - generates code get highest order bit */
8341 /*-----------------------------------------------------------------*/
8342 static void genGetHbit (iCode *ic)
8344 operand *left, *result;
8346 result=IC_RESULT(ic);
8347 pic16_aopOp (left,ic,FALSE);
8348 pic16_aopOp (result,ic,FALSE);
8350 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8351 /* get the highest order byte into a */
8352 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8353 if(AOP_TYPE(result) == AOP_CRY){
8354 pic16_emitcode("rlc","a");
8355 pic16_outBitC(result);
8358 pic16_emitcode("rl","a");
8359 pic16_emitcode("anl","a,#0x01");
8360 pic16_outAcc(result);
8364 pic16_freeAsmop(left,NULL,ic,TRUE);
8365 pic16_freeAsmop(result,NULL,ic,TRUE);
8369 /*-----------------------------------------------------------------*/
8370 /* AccRol - rotate left accumulator by known count */
8371 /*-----------------------------------------------------------------*/
8372 static void AccRol (int shCount)
8374 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8375 shCount &= 0x0007; // shCount : 0..7
8380 pic16_emitcode("rl","a");
8383 pic16_emitcode("rl","a");
8384 pic16_emitcode("rl","a");
8387 pic16_emitcode("swap","a");
8388 pic16_emitcode("rr","a");
8391 pic16_emitcode("swap","a");
8394 pic16_emitcode("swap","a");
8395 pic16_emitcode("rl","a");
8398 pic16_emitcode("rr","a");
8399 pic16_emitcode("rr","a");
8402 pic16_emitcode("rr","a");
8408 /*-----------------------------------------------------------------*/
8409 /* AccLsh - left shift accumulator by known count */
8410 /*-----------------------------------------------------------------*/
8411 static void AccLsh (int shCount)
8413 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8419 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8422 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8423 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8426 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8427 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8430 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8433 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8434 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8437 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8438 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8441 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8445 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8448 /*-----------------------------------------------------------------*/
8449 /* AccRsh - right shift accumulator by known count */
8450 /*-----------------------------------------------------------------*/
8451 static void AccRsh (int shCount, int andmask)
8453 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8458 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8461 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8462 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8465 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8466 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8469 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8472 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8473 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8476 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8477 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8480 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8485 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8487 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8491 /*-----------------------------------------------------------------*/
8492 /* AccSRsh - signed right shift accumulator by known count */
8493 /*-----------------------------------------------------------------*/
8494 static void AccSRsh (int shCount)
8497 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8500 pic16_emitcode("mov","c,acc.7");
8501 pic16_emitcode("rrc","a");
8502 } else if(shCount == 2){
8503 pic16_emitcode("mov","c,acc.7");
8504 pic16_emitcode("rrc","a");
8505 pic16_emitcode("mov","c,acc.7");
8506 pic16_emitcode("rrc","a");
8508 tlbl = newiTempLabel(NULL);
8509 /* rotate right accumulator */
8510 AccRol(8 - shCount);
8511 /* and kill the higher order bits */
8512 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8513 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8514 pic16_emitcode("orl","a,#0x%02x",
8515 (unsigned char)~SRMask[shCount]);
8516 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8522 /*-----------------------------------------------------------------*/
8523 /* shiftR1Left2Result - shift right one byte from left to result */
8524 /*-----------------------------------------------------------------*/
8525 static void shiftR1Left2ResultSigned (operand *left, int offl,
8526 operand *result, int offr,
8531 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8533 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8537 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8539 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8541 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8542 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8548 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8550 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8552 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8553 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8555 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8556 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8562 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8564 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8565 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8568 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8569 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8570 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8572 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8573 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8575 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8579 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8580 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8581 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8582 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8583 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8587 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8589 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8590 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8592 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8593 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8594 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8595 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8596 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8601 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8602 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8603 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8604 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8605 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8606 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8608 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8609 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8610 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8611 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8612 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8618 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8619 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8620 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8621 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8623 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8624 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8625 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8633 /*-----------------------------------------------------------------*/
8634 /* shiftR1Left2Result - shift right one byte from left to result */
8635 /*-----------------------------------------------------------------*/
8636 static void shiftR1Left2Result (operand *left, int offl,
8637 operand *result, int offr,
8638 int shCount, int sign)
8642 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8644 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8646 /* Copy the msb into the carry if signed. */
8648 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8658 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8660 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8661 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8667 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8669 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8670 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8673 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8678 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8680 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8681 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8684 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8685 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8686 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8687 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8691 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8692 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8693 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8697 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8698 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8699 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8701 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8706 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8707 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8708 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8709 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8710 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8715 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8716 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8717 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8726 /*-----------------------------------------------------------------*/
8727 /* shiftL1Left2Result - shift left one byte from left to result */
8728 /*-----------------------------------------------------------------*/
8729 static void shiftL1Left2Result (operand *left, int offl,
8730 operand *result, int offr, int shCount)
8735 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8737 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8738 DEBUGpic16_emitcode ("; ***","same = %d",same);
8739 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8741 /* shift left accumulator */
8742 //AccLsh(shCount); // don't comment out just yet...
8743 // pic16_aopPut(AOP(result),"a",offr);
8747 /* Shift left 1 bit position */
8748 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8750 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8752 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8753 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8757 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8758 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8759 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8760 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8763 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8764 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8765 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8766 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8767 pic16_emitpcode(POC_RLCF, 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));
8775 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8776 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8777 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8778 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8781 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8782 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8783 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8784 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8785 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8788 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8789 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8790 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8794 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8799 /*-----------------------------------------------------------------*/
8800 /* movLeft2Result - move byte from left to result */
8801 /*-----------------------------------------------------------------*/
8802 static void movLeft2Result (operand *left, int offl,
8803 operand *result, int offr)
8806 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8807 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8808 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8810 if (*l == '@' && (IS_AOP_PREG(result))) {
8811 pic16_emitcode("mov","a,%s",l);
8812 pic16_aopPut(AOP(result),"a",offr);
8814 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8815 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8820 /*-----------------------------------------------------------------*/
8821 /* shiftL2Left2Result - shift left two bytes from left to result */
8822 /*-----------------------------------------------------------------*/
8823 static void shiftL2Left2Result (operand *left, int offl,
8824 operand *result, int offr, int shCount)
8826 int same = pic16_sameRegs(AOP(result), AOP(left));
8829 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8831 if (same && (offl != offr)) { // shift bytes
8834 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8835 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8837 } else { // just treat as different later on
8850 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8851 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8852 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8856 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8857 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8863 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8864 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8865 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8866 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8867 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8868 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8869 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8871 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8872 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8876 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8877 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8878 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8879 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8880 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8881 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8882 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8883 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8884 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8885 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8888 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8889 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8890 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8891 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8892 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8902 /* note, use a mov/add for the shift since the mov has a
8903 chance of getting optimized out */
8904 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8905 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8906 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8907 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8908 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8912 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8913 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8919 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8920 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8921 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8922 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8923 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8924 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8925 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8926 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8930 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8931 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8935 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8936 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8937 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8938 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8940 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8941 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8942 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8943 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8944 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8945 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8946 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8947 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8950 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8951 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8952 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8953 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8954 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8959 /*-----------------------------------------------------------------*/
8960 /* shiftR2Left2Result - shift right two bytes from left to result */
8961 /*-----------------------------------------------------------------*/
8962 static void shiftR2Left2Result (operand *left, int offl,
8963 operand *result, int offr,
8964 int shCount, int sign)
8966 int same = pic16_sameRegs(AOP(result), AOP(left));
8968 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8970 if (same && (offl != offr)) { // shift right bytes
8973 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8974 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8976 } else { // just treat as different later on
8988 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8993 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8994 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8996 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8997 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8998 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8999 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9004 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9007 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9008 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9015 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9016 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9017 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9019 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9020 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9021 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9022 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9024 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9025 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9026 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9028 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9029 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9030 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9031 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9032 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9036 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9037 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9041 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9042 pic16_emitpcode(POC_BTFSC,
9043 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9044 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9052 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9053 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9055 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9056 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9057 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9058 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9060 pic16_emitpcode(POC_BTFSC,
9061 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9062 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9064 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9065 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9066 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9067 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9069 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9070 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9071 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9072 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9073 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9074 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9075 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9076 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9078 pic16_emitpcode(POC_BTFSC,
9079 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9080 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9082 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9083 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9090 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9091 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9092 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9093 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9096 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9098 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9103 /*-----------------------------------------------------------------*/
9104 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9105 /*-----------------------------------------------------------------*/
9106 static void shiftLLeftOrResult (operand *left, int offl,
9107 operand *result, int offr, int shCount)
9109 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9111 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9112 /* shift left accumulator */
9114 /* or with result */
9115 /* back to result */
9116 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9119 /*-----------------------------------------------------------------*/
9120 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9121 /*-----------------------------------------------------------------*/
9122 static void shiftRLeftOrResult (operand *left, int offl,
9123 operand *result, int offr, int shCount)
9125 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9127 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9128 /* shift right accumulator */
9130 /* or with result */
9131 /* back to result */
9132 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9135 /*-----------------------------------------------------------------*/
9136 /* genlshOne - left shift a one byte quantity by known count */
9137 /*-----------------------------------------------------------------*/
9138 static void genlshOne (operand *result, operand *left, int shCount)
9140 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9141 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9144 /*-----------------------------------------------------------------*/
9145 /* genlshTwo - left shift two bytes by known amount != 0 */
9146 /*-----------------------------------------------------------------*/
9147 static void genlshTwo (operand *result,operand *left, int shCount)
9151 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9152 size = pic16_getDataSize(result);
9154 /* if shCount >= 8 */
9160 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9162 movLeft2Result(left, LSB, result, MSB16);
9164 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9167 /* 1 <= shCount <= 7 */
9170 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9172 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9176 /*-----------------------------------------------------------------*/
9177 /* shiftLLong - shift left one long from left to result */
9178 /* offr = LSB or MSB16 */
9179 /*-----------------------------------------------------------------*/
9180 static void shiftLLong (operand *left, operand *result, int offr )
9182 int size = AOP_SIZE(result);
9183 int same = pic16_sameRegs(AOP(left),AOP(result));
9186 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9188 if (same && (offr == MSB16)) { //shift one byte
9189 for(i=size-1;i>=MSB16;i--) {
9190 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9191 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9194 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9197 if (size > LSB+offr ){
9199 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9201 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9202 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9206 if(size > MSB16+offr){
9208 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9210 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9211 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9215 if(size > MSB24+offr){
9217 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9219 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9220 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9224 if(size > MSB32+offr){
9226 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9228 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9229 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9233 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9237 /*-----------------------------------------------------------------*/
9238 /* genlshFour - shift four byte by a known amount != 0 */
9239 /*-----------------------------------------------------------------*/
9240 static void genlshFour (operand *result, operand *left, int shCount)
9244 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9245 size = AOP_SIZE(result);
9247 /* if shifting more that 3 bytes */
9248 if (shCount >= 24 ) {
9251 /* lowest order of left goes to the highest
9252 order of the destination */
9253 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9255 movLeft2Result(left, LSB, result, MSB32);
9257 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9258 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9259 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9264 /* more than two bytes */
9265 else if ( shCount >= 16 ) {
9266 /* lower order two bytes goes to higher order two bytes */
9268 /* if some more remaining */
9270 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9272 movLeft2Result(left, MSB16, result, MSB32);
9273 movLeft2Result(left, LSB, result, MSB24);
9275 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9276 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9280 /* if more than 1 byte */
9281 else if ( shCount >= 8 ) {
9282 /* lower order three bytes goes to higher order three bytes */
9286 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9288 movLeft2Result(left, LSB, result, MSB16);
9290 else{ /* size = 4 */
9292 movLeft2Result(left, MSB24, result, MSB32);
9293 movLeft2Result(left, MSB16, result, MSB24);
9294 movLeft2Result(left, LSB, result, MSB16);
9295 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9297 else if(shCount == 1)
9298 shiftLLong(left, result, MSB16);
9300 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9301 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9302 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9303 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9308 /* 1 <= shCount <= 7 */
9309 else if(shCount <= 3)
9311 shiftLLong(left, result, LSB);
9312 while(--shCount >= 1)
9313 shiftLLong(result, result, LSB);
9315 /* 3 <= shCount <= 7, optimize */
9317 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9318 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9319 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9323 /*-----------------------------------------------------------------*/
9324 /* genLeftShiftLiteral - left shifting by known count */
9325 /*-----------------------------------------------------------------*/
9326 void pic16_genLeftShiftLiteral (operand *left,
9331 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9335 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9336 pic16_freeAsmop(right,NULL,ic,TRUE);
9338 pic16_aopOp(left,ic,FALSE);
9339 pic16_aopOp(result,ic,TRUE);
9341 size = getSize(operandType(result));
9344 pic16_emitcode("; shift left ","result %d, left %d",size,
9348 /* I suppose that the left size >= result size */
9351 movLeft2Result(left, size, result, size);
9355 else if(shCount >= (size * 8))
9357 pic16_aopPut(AOP(result),zero,size);
9361 genlshOne (result,left,shCount);
9366 genlshTwo (result,left,shCount);
9370 genlshFour (result,left,shCount);
9374 pic16_freeAsmop(left,NULL,ic,TRUE);
9375 pic16_freeAsmop(result,NULL,ic,TRUE);
9378 /*-----------------------------------------------------------------*
9379 * genMultiAsm - repeat assembly instruction for size of register.
9380 * if endian == 1, then the high byte (i.e base address + size of
9381 * register) is used first else the low byte is used first;
9382 *-----------------------------------------------------------------*/
9383 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9388 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9401 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9407 #if !(USE_GENERIC_SIGNED_SHIFT)
9408 /*-----------------------------------------------------------------*/
9409 /* genLeftShift - generates code for left shifting */
9410 /*-----------------------------------------------------------------*/
9411 static void genLeftShift (iCode *ic)
9413 operand *left,*right, *result;
9416 symbol *tlbl , *tlbl1;
9419 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9421 right = IC_RIGHT(ic);
9423 result = IC_RESULT(ic);
9425 pic16_aopOp(right,ic,FALSE);
9427 /* if the shift count is known then do it
9428 as efficiently as possible */
9429 if (AOP_TYPE(right) == AOP_LIT) {
9430 pic16_genLeftShiftLiteral (left,right,result,ic);
9434 /* shift count is unknown then we have to form
9435 * a loop. Get the loop count in WREG : Note: we take
9436 * only the lower order byte since shifting
9437 * more than 32 bits make no sense anyway, ( the
9438 * largest size of an object can be only 32 bits ) */
9440 pic16_aopOp(left,ic,FALSE);
9441 pic16_aopOp(result,ic,FALSE);
9443 /* now move the left to the result if they are not the
9444 * same, and if size > 1,
9445 * and if right is not same to result (!!!) -- VR */
9446 if (!pic16_sameRegs(AOP(left),AOP(result))
9447 && (AOP_SIZE(result) > 1)) {
9449 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9451 size = AOP_SIZE(result);
9456 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9457 if (*l == '@' && (IS_AOP_PREG(result))) {
9459 pic16_emitcode("mov","a,%s",l);
9460 pic16_aopPut(AOP(result),"a",offset);
9464 /* we don't know if left is a literal or a register, take care -- VR */
9465 pic16_mov2f(AOP(result), AOP(left), offset);
9471 size = AOP_SIZE(result);
9473 /* if it is only one byte then */
9475 if(optimized_for_speed) {
9476 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9477 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9478 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9479 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9480 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9481 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9482 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9483 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9484 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9485 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9486 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9487 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9490 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9492 tlbl = newiTempLabel(NULL);
9495 /* this is already done, why change it? */
9496 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9497 pic16_mov2f(AOP(result), AOP(left), 0);
9501 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9502 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9503 pic16_emitpLabel(tlbl->key);
9504 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9505 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9507 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9512 if (pic16_sameRegs(AOP(left),AOP(result))) {
9514 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9516 tlbl = newiTempLabel(NULL);
9517 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9518 genMultiAsm(POC_RRCF, result, size,1);
9519 pic16_emitpLabel(tlbl->key);
9520 genMultiAsm(POC_RLCF, result, size,0);
9521 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9523 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9527 //tlbl = newiTempLabel(NULL);
9529 //tlbl1 = newiTempLabel(NULL);
9531 //reAdjustPreg(AOP(result));
9533 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9534 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9535 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9537 //pic16_emitcode("add","a,acc");
9538 //pic16_aopPut(AOP(result),"a",offset++);
9540 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9542 // pic16_emitcode("rlc","a");
9543 // pic16_aopPut(AOP(result),"a",offset++);
9545 //reAdjustPreg(AOP(result));
9547 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9548 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9551 tlbl = newiTempLabel(NULL);
9552 tlbl1= newiTempLabel(NULL);
9554 size = AOP_SIZE(result);
9557 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9559 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9561 /* offset should be 0, 1 or 3 */
9563 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9565 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9567 pic16_emitpcode(POC_MOVWF, pctemp);
9570 pic16_emitpLabel(tlbl->key);
9573 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9575 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9577 pic16_emitpcode(POC_DECFSZ, pctemp);
9578 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9579 pic16_emitpLabel(tlbl1->key);
9581 pic16_popReleaseTempReg(pctemp,1);
9585 pic16_freeAsmop (right,NULL,ic,TRUE);
9586 pic16_freeAsmop(left,NULL,ic,TRUE);
9587 pic16_freeAsmop(result,NULL,ic,TRUE);
9593 #error old code (left here for reference)
9594 /*-----------------------------------------------------------------*/
9595 /* genLeftShift - generates code for left shifting */
9596 /*-----------------------------------------------------------------*/
9597 static void genLeftShift (iCode *ic)
9599 operand *left,*right, *result;
9602 symbol *tlbl , *tlbl1;
9605 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9607 right = IC_RIGHT(ic);
9609 result = IC_RESULT(ic);
9611 pic16_aopOp(right,ic,FALSE);
9613 /* if the shift count is known then do it
9614 as efficiently as possible */
9615 if (AOP_TYPE(right) == AOP_LIT) {
9616 pic16_genLeftShiftLiteral (left,right,result,ic);
9620 /* shift count is unknown then we have to form
9621 a loop get the loop count in B : Note: we take
9622 only the lower order byte since shifting
9623 more that 32 bits make no sense anyway, ( the
9624 largest size of an object can be only 32 bits ) */
9627 pic16_aopOp(left,ic,FALSE);
9628 pic16_aopOp(result,ic,FALSE);
9630 /* now move the left to the result if they are not the
9632 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9633 AOP_SIZE(result) > 1) {
9635 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9637 size = AOP_SIZE(result);
9640 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9641 if (*l == '@' && (IS_AOP_PREG(result))) {
9643 pic16_emitcode("mov","a,%s",l);
9644 pic16_aopPut(AOP(result),"a",offset);
9647 /* we don't know if left is a literal or a register, take care -- VR */
9648 pic16_mov2f(AOP(result), AOP(left), offset);
9654 size = AOP_SIZE(result);
9656 /* if it is only one byte then */
9658 if(optimized_for_speed) {
9659 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9660 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9661 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9662 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9663 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9664 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9665 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9666 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9667 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9668 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9669 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9670 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9673 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9675 tlbl = newiTempLabel(NULL);
9676 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9677 pic16_mov2f(AOP(result), AOP(left), 0);
9679 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9680 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9683 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9684 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9685 pic16_emitpLabel(tlbl->key);
9686 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9687 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9689 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9694 if (pic16_sameRegs(AOP(left),AOP(result))) {
9696 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9698 tlbl = newiTempLabel(NULL);
9699 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9700 genMultiAsm(POC_RRCF, result, size,1);
9701 pic16_emitpLabel(tlbl->key);
9702 genMultiAsm(POC_RLCF, result, size,0);
9703 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9705 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9709 //tlbl = newiTempLabel(NULL);
9711 //tlbl1 = newiTempLabel(NULL);
9713 //reAdjustPreg(AOP(result));
9715 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9716 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9717 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9719 //pic16_emitcode("add","a,acc");
9720 //pic16_aopPut(AOP(result),"a",offset++);
9722 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9724 // pic16_emitcode("rlc","a");
9725 // pic16_aopPut(AOP(result),"a",offset++);
9727 //reAdjustPreg(AOP(result));
9729 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9730 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9733 tlbl = newiTempLabel(NULL);
9734 tlbl1= newiTempLabel(NULL);
9736 size = AOP_SIZE(result);
9739 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9741 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9743 /* offset should be 0, 1 or 3 */
9745 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9747 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9749 pic16_emitpcode(POC_MOVWF, pctemp);
9752 pic16_emitpLabel(tlbl->key);
9755 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9757 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9759 pic16_emitpcode(POC_DECFSZ, pctemp);
9760 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9761 pic16_emitpLabel(tlbl1->key);
9763 pic16_popReleaseTempReg(pctemp,1);
9767 pic16_freeAsmop (right,NULL,ic,TRUE);
9768 pic16_freeAsmop(left,NULL,ic,TRUE);
9769 pic16_freeAsmop(result,NULL,ic,TRUE);
9773 /*-----------------------------------------------------------------*/
9774 /* genrshOne - right shift a one byte quantity by known count */
9775 /*-----------------------------------------------------------------*/
9776 static void genrshOne (operand *result, operand *left,
9777 int shCount, int sign)
9779 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9780 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9783 /*-----------------------------------------------------------------*/
9784 /* genrshTwo - right shift two bytes by known amount != 0 */
9785 /*-----------------------------------------------------------------*/
9786 static void genrshTwo (operand *result,operand *left,
9787 int shCount, int sign)
9789 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9790 /* if shCount >= 8 */
9794 shiftR1Left2Result(left, MSB16, result, LSB,
9797 movLeft2Result(left, MSB16, result, LSB);
9799 pic16_addSign (result, 1, sign);
9802 /* 1 <= shCount <= 7 */
9804 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9807 /*-----------------------------------------------------------------*/
9808 /* shiftRLong - shift right one long from left to result */
9809 /* offl = LSB or MSB16 */
9810 /*-----------------------------------------------------------------*/
9811 static void shiftRLong (operand *left, int offl,
9812 operand *result, int sign)
9814 int size = AOP_SIZE(result);
9815 int same = pic16_sameRegs(AOP(left),AOP(result));
9817 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9819 if (same && (offl == MSB16)) { //shift one byte right
9820 for(i=MSB16;i<size;i++) {
9821 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9822 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9827 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9833 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9835 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9836 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9840 /* add sign of "a" */
9841 pic16_addSign(result, MSB32, sign);
9845 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9847 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9848 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9852 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9854 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9855 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9859 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9862 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9863 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9868 /*-----------------------------------------------------------------*/
9869 /* genrshFour - shift four byte by a known amount != 0 */
9870 /*-----------------------------------------------------------------*/
9871 static void genrshFour (operand *result, operand *left,
9872 int shCount, int sign)
9874 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9875 /* if shifting more that 3 bytes */
9876 if(shCount >= 24 ) {
9879 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9881 movLeft2Result(left, MSB32, result, LSB);
9883 pic16_addSign(result, MSB16, sign);
9885 else if(shCount >= 16){
9888 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9890 movLeft2Result(left, MSB24, result, LSB);
9891 movLeft2Result(left, MSB32, result, MSB16);
9893 pic16_addSign(result, MSB24, sign);
9895 else if(shCount >= 8){
9898 shiftRLong(left, MSB16, result, sign);
9899 else if(shCount == 0){
9900 movLeft2Result(left, MSB16, result, LSB);
9901 movLeft2Result(left, MSB24, result, MSB16);
9902 movLeft2Result(left, MSB32, result, MSB24);
9903 pic16_addSign(result, MSB32, sign);
9905 else{ //shcount >= 2
9906 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9907 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9908 /* the last shift is signed */
9909 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9910 pic16_addSign(result, MSB32, sign);
9913 else{ /* 1 <= shCount <= 7 */
9915 shiftRLong(left, LSB, result, sign);
9917 shiftRLong(result, LSB, result, sign);
9920 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9921 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9922 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9927 /*-----------------------------------------------------------------*/
9928 /* genRightShiftLiteral - right shifting by known count */
9929 /*-----------------------------------------------------------------*/
9930 static void genRightShiftLiteral (operand *left,
9936 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9939 pic16_freeAsmop(right,NULL,ic,TRUE);
9941 pic16_aopOp(left,ic,FALSE);
9942 pic16_aopOp(result,ic,TRUE);
9944 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9947 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9951 lsize = pic16_getDataSize(left);
9952 res_size = pic16_getDataSize(result);
9953 /* test the LEFT size !!! */
9955 /* I suppose that the left size >= result size */
9957 assert (res_size <= lsize);
9958 while (res_size--) {
9959 pic16_mov2f (AOP(result), AOP(left), res_size);
9963 else if(shCount >= (lsize * 8)){
9966 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9968 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9969 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
9974 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9975 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9976 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9978 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9983 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9990 genrshOne (result,left,shCount,sign);
9994 genrshTwo (result,left,shCount,sign);
9998 genrshFour (result,left,shCount,sign);
10006 pic16_freeAsmop(left,NULL,ic,TRUE);
10007 pic16_freeAsmop(result,NULL,ic,TRUE);
10010 #if !(USE_GENERIC_SIGNED_SHIFT)
10011 /*-----------------------------------------------------------------*/
10012 /* genSignedRightShift - right shift of signed number */
10013 /*-----------------------------------------------------------------*/
10014 static void genSignedRightShift (iCode *ic)
10016 operand *right, *left, *result;
10019 symbol *tlbl, *tlbl1 ;
10022 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10024 /* we do it the hard way put the shift count in b
10025 and loop thru preserving the sign */
10026 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10028 right = IC_RIGHT(ic);
10029 left = IC_LEFT(ic);
10030 result = IC_RESULT(ic);
10032 pic16_aopOp(right,ic,FALSE);
10033 pic16_aopOp(left,ic,FALSE);
10034 pic16_aopOp(result,ic,FALSE);
10037 if ( AOP_TYPE(right) == AOP_LIT) {
10038 genRightShiftLiteral (left,right,result,ic,1);
10041 /* shift count is unknown then we have to form
10042 a loop get the loop count in B : Note: we take
10043 only the lower order byte since shifting
10044 more that 32 bits make no sense anyway, ( the
10045 largest size of an object can be only 32 bits ) */
10047 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10048 //pic16_emitcode("inc","b");
10049 //pic16_freeAsmop (right,NULL,ic,TRUE);
10050 //pic16_aopOp(left,ic,FALSE);
10051 //pic16_aopOp(result,ic,FALSE);
10053 /* now move the left to the result if they are not the
10055 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10056 AOP_SIZE(result) > 1) {
10058 size = AOP_SIZE(result);
10062 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10063 if (*l == '@' && IS_AOP_PREG(result)) {
10065 pic16_emitcode("mov","a,%s",l);
10066 pic16_aopPut(AOP(result),"a",offset);
10068 pic16_aopPut(AOP(result),l,offset);
10070 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10071 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10077 /* mov the highest order bit to OVR */
10078 tlbl = newiTempLabel(NULL);
10079 tlbl1= newiTempLabel(NULL);
10081 size = AOP_SIZE(result);
10084 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10086 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10088 /* offset should be 0, 1 or 3 */
10089 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10091 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10093 pic16_emitpcode(POC_MOVWF, pctemp);
10096 pic16_emitpLabel(tlbl->key);
10098 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10099 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10102 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10105 pic16_emitpcode(POC_DECFSZ, pctemp);
10106 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10107 pic16_emitpLabel(tlbl1->key);
10109 pic16_popReleaseTempReg(pctemp,1);
10111 size = AOP_SIZE(result);
10113 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10114 pic16_emitcode("rlc","a");
10115 pic16_emitcode("mov","ov,c");
10116 /* if it is only one byte then */
10118 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10120 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10121 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10122 pic16_emitcode("mov","c,ov");
10123 pic16_emitcode("rrc","a");
10124 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10125 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10126 pic16_aopPut(AOP(result),"a",0);
10130 reAdjustPreg(AOP(result));
10131 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10132 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10133 pic16_emitcode("mov","c,ov");
10135 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10137 pic16_emitcode("rrc","a");
10138 pic16_aopPut(AOP(result),"a",offset--);
10140 reAdjustPreg(AOP(result));
10141 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10142 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10147 pic16_freeAsmop(left,NULL,ic,TRUE);
10148 pic16_freeAsmop(result,NULL,ic,TRUE);
10149 pic16_freeAsmop(right,NULL,ic,TRUE);
10153 #if !(USE_GENERIC_SIGNED_SHIFT)
10154 #warning This implementation of genRightShift() is incomplete!
10155 /*-----------------------------------------------------------------*/
10156 /* genRightShift - generate code for right shifting */
10157 /*-----------------------------------------------------------------*/
10158 static void genRightShift (iCode *ic)
10160 operand *right, *left, *result;
10164 symbol *tlbl, *tlbl1 ;
10166 /* if signed then we do it the hard way preserve the
10167 sign bit moving it inwards */
10168 letype = getSpec(operandType(IC_LEFT(ic)));
10169 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10171 if (!SPEC_USIGN(letype)) {
10172 genSignedRightShift (ic);
10176 /* signed & unsigned types are treated the same : i.e. the
10177 signed is NOT propagated inwards : quoting from the
10178 ANSI - standard : "for E1 >> E2, is equivalent to division
10179 by 2**E2 if unsigned or if it has a non-negative value,
10180 otherwise the result is implementation defined ", MY definition
10181 is that the sign does not get propagated */
10183 right = IC_RIGHT(ic);
10184 left = IC_LEFT(ic);
10185 result = IC_RESULT(ic);
10187 pic16_aopOp(right,ic,FALSE);
10189 /* if the shift count is known then do it
10190 as efficiently as possible */
10191 if (AOP_TYPE(right) == AOP_LIT) {
10192 genRightShiftLiteral (left,right,result,ic, 0);
10196 /* shift count is unknown then we have to form
10197 a loop get the loop count in B : Note: we take
10198 only the lower order byte since shifting
10199 more that 32 bits make no sense anyway, ( the
10200 largest size of an object can be only 32 bits ) */
10202 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10203 pic16_emitcode("inc","b");
10204 pic16_aopOp(left,ic,FALSE);
10205 pic16_aopOp(result,ic,FALSE);
10207 /* now move the left to the result if they are not the
10209 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10210 AOP_SIZE(result) > 1) {
10212 size = AOP_SIZE(result);
10215 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10216 if (*l == '@' && IS_AOP_PREG(result)) {
10218 pic16_emitcode("mov","a,%s",l);
10219 pic16_aopPut(AOP(result),"a",offset);
10221 pic16_aopPut(AOP(result),l,offset);
10226 tlbl = newiTempLabel(NULL);
10227 tlbl1= newiTempLabel(NULL);
10228 size = AOP_SIZE(result);
10231 /* if it is only one byte then */
10234 tlbl = newiTempLabel(NULL);
10235 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10236 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10237 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10240 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10241 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10242 pic16_emitpLabel(tlbl->key);
10243 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10244 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10246 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10251 reAdjustPreg(AOP(result));
10252 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10253 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10256 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10258 pic16_emitcode("rrc","a");
10259 pic16_aopPut(AOP(result),"a",offset--);
10261 reAdjustPreg(AOP(result));
10263 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10264 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10267 pic16_freeAsmop(left,NULL,ic,TRUE);
10268 pic16_freeAsmop (right,NULL,ic,TRUE);
10269 pic16_freeAsmop(result,NULL,ic,TRUE);
10273 #if (USE_GENERIC_SIGNED_SHIFT)
10274 /*-----------------------------------------------------------------*/
10275 /* genGenericShift - generates code for left or right shifting */
10276 /*-----------------------------------------------------------------*/
10277 static void genGenericShift (iCode *ic, int isShiftLeft) {
10278 operand *left,*right, *result;
10280 int sign, signedCount;
10281 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10282 PIC_OPCODE pos_shift, neg_shift;
10286 right = IC_RIGHT(ic);
10287 left = IC_LEFT(ic);
10288 result = IC_RESULT(ic);
10290 pic16_aopOp(right,ic,FALSE);
10291 pic16_aopOp(left,ic,FALSE);
10292 pic16_aopOp(result,ic,TRUE);
10294 sign = !SPEC_USIGN(operandType (left));
10295 signedCount = !SPEC_USIGN(operandType (right));
10297 /* if the shift count is known then do it
10298 as efficiently as possible */
10299 if (AOP_TYPE(right) == AOP_LIT) {
10300 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10301 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10302 // we should modify right->aopu.aop_lit here!
10303 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10304 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10306 pic16_genLeftShiftLiteral (left,right,result,ic);
10308 genRightShiftLiteral (left,right,result,ic, sign);
10311 } // if (right is literal)
10313 /* shift count is unknown then we have to form a loop.
10314 * Note: we take only the lower order byte since shifting
10315 * more than 32 bits make no sense anyway, ( the
10316 * largest size of an object can be only 32 bits )
10317 * Note: we perform arithmetic shifts if the left operand is
10318 * signed and we do an (effective) right shift, i. e. we
10319 * shift in the sign bit from the left. */
10321 label_complete = newiTempLabel ( NULL );
10322 label_loop_pos = newiTempLabel ( NULL );
10323 label_loop_neg = NULL;
10324 label_negative = NULL;
10325 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10326 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10329 // additional labels needed
10330 label_loop_neg = newiTempLabel ( NULL );
10331 label_negative = newiTempLabel ( NULL );
10334 // copy source to result -- this will effectively truncate the left operand to the size of result!
10335 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10336 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10337 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10338 pic16_mov2f (AOP(result),AOP(left), offset);
10341 // if result is longer than left, fill with zeros (or sign)
10342 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10343 if (sign && AOP_SIZE(left) > 0) {
10344 // shift signed operand -- fill with sign
10345 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10346 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10347 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10348 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10349 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10352 // shift unsigned operand -- fill result with zeros
10353 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10354 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10357 } // if (size mismatch)
10359 pic16_mov2w (AOP(right), 0);
10360 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10361 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10364 // perform a shift by one (shift count is positive)
10365 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10366 // 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])
10367 pic16_emitpLabel (label_loop_pos->key);
10369 if (sign && (pos_shift == POC_RRCF)) {
10370 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10373 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10374 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10375 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10377 // perform a shift by one (shift count is positive)
10378 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10379 // 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])
10380 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10381 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10383 pic16_emitpLabel (label_loop_pos->key);
10384 if (sign && (pos_shift == POC_RRCF)) {
10385 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10388 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10389 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10390 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10391 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10395 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10397 pic16_emitpLabel (label_negative->key);
10398 // perform a shift by -1 (shift count is negative)
10399 // 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)
10401 pic16_emitpLabel (label_loop_neg->key);
10402 if (sign && (neg_shift == POC_RRCF)) {
10403 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10406 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10407 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10408 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10409 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10410 } // if (signedCount)
10412 pic16_emitpLabel (label_complete->key);
10415 pic16_freeAsmop (right,NULL,ic,TRUE);
10416 pic16_freeAsmop(left,NULL,ic,TRUE);
10417 pic16_freeAsmop(result,NULL,ic,TRUE);
10420 static void genLeftShift (iCode *ic) {
10421 genGenericShift (ic, 1);
10424 static void genRightShift (iCode *ic) {
10425 genGenericShift (ic, 0);
10430 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10431 void pic16_loadFSR0(operand *op, int lit)
10433 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10434 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10436 assert (!OP_SYMBOL(op)->remat);
10437 // set up FSR0 with address of result
10438 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10439 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10443 /*----------------------------------------------------------------*/
10444 /* pic16_derefPtr - move one byte from the location ptr points to */
10445 /* to WREG (doWrite == 0) or one byte from WREG */
10446 /* to the location ptr points to (doWrite != 0) */
10447 /*----------------------------------------------------------------*/
10448 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10453 if (!fsr0_setup || !*fsr0_setup)
10455 pic16_loadFSR0( ptr, 0 );
10456 if (fsr0_setup) *fsr0_setup = 1;
10459 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10461 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10465 if (AOP(ptr)->aopu.aop_reg[2]) {
10466 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10467 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10468 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10469 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl)));
10470 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(ptr),2));
10471 pic16_callGenericPointerRW(doWrite, 1);
10473 // data pointer (just 2 byte given)
10474 if (!fsr0_setup || !*fsr0_setup)
10476 pic16_loadFSR0( ptr, 0 );
10477 if (fsr0_setup) *fsr0_setup = 1;
10480 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10482 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10487 assert (0 && "invalid pointer type specified");
10492 /*-----------------------------------------------------------------*/
10493 /* genUnpackBits - generates code for unpacking bits */
10494 /*-----------------------------------------------------------------*/
10495 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10498 sym_link *etype, *letype;
10499 int blen=0, bstr=0;
10502 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10503 etype = getSpec(operandType(result));
10504 letype = getSpec(operandType(left));
10506 // if(IS_BITFIELD(etype)) {
10507 blen = SPEC_BLEN(etype);
10508 bstr = SPEC_BSTR(etype);
10511 lbstr = SPEC_BSTR( letype );
10514 if((blen == 1) && (bstr < 8)) {
10515 /* it is a single bit, so use the appropriate bit instructions */
10516 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10518 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10520 // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10521 if(!IS_PTR(operandType(left))/* && OP_SYMBOL(left)->remat && (ptype == POINTER)*/) {
10522 /* workaround to reduce the extra lfsr instruction */
10523 pic16_emitpcode(POC_BTFSC,
10524 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10526 pic16_loadFSR0 (left, 0);
10527 pic16_emitpcode(POC_BTFSC,
10528 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10531 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10533 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10539 /* the following call to pic16_loadFSR0 is temporary until
10540 * optimization to handle single bit assignments is added
10541 * to the function. Until then use the old safe way! -- VR */
10543 if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
10544 // access symbol directly
10545 pic16_mov2w (AOP(left), 0);
10547 pic16_derefPtr (left, ptype, 0, NULL);
10550 /* if we have bitdisplacement then it fits */
10551 /* into this byte completely or if length is */
10552 /* less than a byte */
10553 if ((shCnt = SPEC_BSTR(etype)) ||
10554 (SPEC_BLEN(etype) <= 8)) {
10556 /* shift right acc */
10559 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10560 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10562 /* VR -- normally I would use the following, but since we use the hack,
10563 * to avoid the masking from AccRsh, why not mask it right now? */
10566 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10569 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10575 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10576 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10583 static void genDataPointerGet(operand *left,
10587 int size, offset = 0, leoffset=0 ;
10589 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10590 pic16_aopOp(result, ic, TRUE);
10594 size = AOP_SIZE(result);
10595 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10599 /* The following tests may save a redudant movff instruction when
10600 * accessing unions */
10602 /* if they are the same */
10603 if (operandsEqu (left, result)) {
10604 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10610 /* if they are the same registers */
10611 if (pic16_sameRegs(AOP(left),AOP(result))) {
10612 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10618 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10619 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10620 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10627 if ( AOP_TYPE(left) == AOP_PCODE) {
10628 fprintf(stderr,"genDataPointerGet %s, %d\n",
10629 AOP(left)->aopu.pcop->name,
10630 (AOP(left)->aopu.pcop->type == PO_DIR)?
10631 PCOR(AOP(left)->aopu.pcop)->instance:
10632 PCOI(AOP(left)->aopu.pcop)->offset);
10636 if(AOP(left)->aopu.pcop->type == PO_DIR)
10637 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10639 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10642 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10644 // pic16_DumpOp("(result)",result);
10645 if(is_LitAOp(AOP(result))) {
10646 pic16_mov2w(AOP(left), offset); // patch 8
10647 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10649 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10650 pic16_popGet(AOP(left), offset), //patch 8
10651 pic16_popGet(AOP(result), offset)));
10659 pic16_freeAsmop(result,NULL,ic,TRUE);
10664 /*-----------------------------------------------------------------*/
10665 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10666 /*-----------------------------------------------------------------*/
10667 static void genNearPointerGet (operand *left,
10671 // asmop *aop = NULL;
10672 //regs *preg = NULL ;
10673 sym_link *rtype, *retype;
10674 sym_link *ltype, *letype;
10678 rtype = operandType(result);
10679 retype= getSpec(rtype);
10680 ltype = operandType(left);
10681 letype= getSpec(ltype);
10683 pic16_aopOp(left,ic,FALSE);
10685 // pic16_DumpOp("(left)",left);
10686 // pic16_DumpOp("(result)",result);
10688 /* if left is rematerialisable and
10689 * result is not bit variable type and
10690 * the left is pointer to data space i.e
10691 * lower 128 bytes of space */
10693 if (AOP_TYPE(left) == AOP_PCODE
10694 && !IS_BITFIELD(retype)
10695 && DCL_TYPE(ltype) == POINTER) {
10697 genDataPointerGet (left,result,ic);
10698 pic16_freeAsmop(left, NULL, ic, TRUE);
10702 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10703 pic16_aopOp (result,ic,TRUE);
10705 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10708 if(IS_BITFIELD( retype )
10709 && (SPEC_BLEN(operandType(result))==1)
10713 int bitstrt, bytestrt;
10715 /* if this is bitfield of size 1, see if we are checking the value
10716 * of a single bit in an if-statement,
10717 * if yes, then don't generate usual code, but execute the
10718 * genIfx directly -- VR */
10722 /* CHECK: if next iCode is IFX
10723 * and current result operand is nextic's conditional operand
10724 * and current result operand live ranges ends at nextic's key number
10726 if((nextic->op == IFX)
10727 && (result == IC_COND(nextic))
10728 && (OP_LIVETO(result) == nextic->seq)
10729 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10731 /* everything is ok then */
10732 /* find a way to optimize the genIfx iCode */
10734 bytestrt = SPEC_BSTR(operandType(result))/8;
10735 bitstrt = SPEC_BSTR(operandType(result))%8;
10737 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10739 genIfxpCOpJump(nextic, jop);
10741 pic16_freeAsmop(left, NULL, ic, TRUE);
10742 pic16_freeAsmop(result, NULL, ic, TRUE);
10748 /* if bitfield then unpack the bits */
10749 if (IS_BITFIELD(letype))
10750 genUnpackBits (result, left, NULL, POINTER);
10752 /* we have can just get the values */
10753 int size = AOP_SIZE(result);
10756 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10758 pic16_loadFSR0( left, 0 );
10762 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10763 pic16_popGet(AOP(result), offset++)));
10765 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10766 pic16_popGet(AOP(result), offset++)));
10772 /* now some housekeeping stuff */
10774 /* we had to allocate for this iCode */
10775 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10776 pic16_freeAsmop(NULL,aop,ic,TRUE);
10778 /* we did not allocate which means left
10779 * already in a pointer register, then
10780 * if size > 0 && this could be used again
10781 * we have to point it back to where it
10783 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10784 if (AOP_SIZE(result) > 1
10785 && !OP_SYMBOL(left)->remat
10786 && ( OP_SYMBOL(left)->liveTo > ic->seq
10788 // int size = AOP_SIZE(result) - 1;
10790 // pic16_emitcode("dec","%s",rname);
10796 pic16_freeAsmop(left,NULL,ic,TRUE);
10797 pic16_freeAsmop(result,NULL,ic,TRUE);
10800 /*-----------------------------------------------------------------*/
10801 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10802 /*-----------------------------------------------------------------*/
10803 static void genPagedPointerGet (operand *left,
10808 regs *preg = NULL ;
10810 sym_link *rtype, *retype;
10812 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10814 rtype = operandType(result);
10815 retype= getSpec(rtype);
10817 pic16_aopOp(left,ic,FALSE);
10819 /* if the value is already in a pointer register
10820 then don't need anything more */
10821 if (!AOP_INPREG(AOP(left))) {
10822 /* otherwise get a free pointer register */
10824 preg = getFreePtr(ic,&aop,FALSE);
10825 pic16_emitcode("mov","%s,%s",
10827 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10828 rname = preg->name ;
10830 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10832 pic16_freeAsmop(left,NULL,ic,TRUE);
10833 pic16_aopOp (result,ic,TRUE);
10835 /* if bitfield then unpack the bits */
10836 if (IS_BITFIELD(retype))
10837 genUnpackBits (result,left,rname,PPOINTER);
10839 /* we have can just get the values */
10840 int size = AOP_SIZE(result);
10845 pic16_emitcode("movx","a,@%s",rname);
10846 pic16_aopPut(AOP(result),"a",offset);
10851 pic16_emitcode("inc","%s",rname);
10855 /* now some housekeeping stuff */
10857 /* we had to allocate for this iCode */
10858 pic16_freeAsmop(NULL,aop,ic,TRUE);
10860 /* we did not allocate which means left
10861 already in a pointer register, then
10862 if size > 0 && this could be used again
10863 we have to point it back to where it
10865 if (AOP_SIZE(result) > 1 &&
10866 !OP_SYMBOL(left)->remat &&
10867 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10869 int size = AOP_SIZE(result) - 1;
10871 pic16_emitcode("dec","%s",rname);
10876 pic16_freeAsmop(result,NULL,ic,TRUE);
10882 /* This code is not adjusted to PIC16 and fails utterly.
10883 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10885 /*-----------------------------------------------------------------*/
10886 /* genFarPointerGet - gget value from far space */
10887 /*-----------------------------------------------------------------*/
10888 static void genFarPointerGet (operand *left,
10889 operand *result, iCode *ic)
10892 sym_link *retype = getSpec(operandType(result));
10894 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10896 pic16_aopOp(left,ic,FALSE);
10898 /* if the operand is already in dptr
10899 then we do nothing else we move the value to dptr */
10900 if (AOP_TYPE(left) != AOP_STR) {
10901 /* if this is remateriazable */
10902 if (AOP_TYPE(left) == AOP_IMMD)
10903 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10904 else { /* we need to get it byte by byte */
10905 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10906 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10907 if (options.model == MODEL_FLAT24)
10909 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10913 /* so dptr know contains the address */
10914 pic16_freeAsmop(left,NULL,ic,TRUE);
10915 pic16_aopOp(result,ic,TRUE);
10917 /* if bit then unpack */
10918 if (IS_BITFIELD(retype))
10919 genUnpackBits(result,left,"dptr",FPOINTER);
10921 size = AOP_SIZE(result);
10925 pic16_emitcode("movx","a,@dptr");
10926 pic16_aopPut(AOP(result),"a",offset++);
10928 pic16_emitcode("inc","dptr");
10932 pic16_freeAsmop(result,NULL,ic,TRUE);
10937 /*-----------------------------------------------------------------*/
10938 /* genCodePointerGet - get value from code space */
10939 /*-----------------------------------------------------------------*/
10940 static void genCodePointerGet (operand *left,
10941 operand *result, iCode *ic)
10944 sym_link *retype = getSpec(operandType(result));
10946 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10948 pic16_aopOp(left,ic,FALSE);
10950 /* if the operand is already in dptr
10951 then we do nothing else we move the value to dptr */
10952 if (AOP_TYPE(left) != AOP_STR) {
10953 /* if this is remateriazable */
10954 if (AOP_TYPE(left) == AOP_IMMD)
10955 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10956 else { /* we need to get it byte by byte */
10957 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10958 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10959 if (options.model == MODEL_FLAT24)
10961 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10965 /* so dptr know contains the address */
10966 pic16_freeAsmop(left,NULL,ic,TRUE);
10967 pic16_aopOp(result,ic,FALSE);
10969 /* if bit then unpack */
10970 if (IS_BITFIELD(retype))
10971 genUnpackBits(result,left,"dptr",CPOINTER);
10973 size = AOP_SIZE(result);
10977 pic16_emitcode("clr","a");
10978 pic16_emitcode("movc","a,@a+dptr");
10979 pic16_aopPut(AOP(result),"a",offset++);
10981 pic16_emitcode("inc","dptr");
10985 pic16_freeAsmop(result,NULL,ic,TRUE);
10990 /*-----------------------------------------------------------------*/
10991 /* genGenPointerGet - gget value from generic pointer space */
10992 /*-----------------------------------------------------------------*/
10993 static void genGenPointerGet (operand *left,
10994 operand *result, iCode *ic)
10996 int size, offset, lit;
10997 sym_link *retype = getSpec(operandType(result));
10999 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11000 pic16_aopOp(left,ic,FALSE);
11001 pic16_aopOp(result,ic,FALSE);
11002 size = AOP_SIZE(result);
11004 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11006 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11008 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11009 // load FSR0 from immediate
11010 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11012 // pic16_loadFSR0( left );
11017 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11019 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11026 else { /* we need to get it byte by byte */
11027 // set up FSR0 with address from left
11028 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11029 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11035 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11037 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11044 /* if bit then unpack */
11045 if (IS_BITFIELD(retype))
11046 genUnpackBits(result,left,"BAD",GPOINTER);
11049 pic16_freeAsmop(left,NULL,ic,TRUE);
11050 pic16_freeAsmop(result,NULL,ic,TRUE);
11056 /*-----------------------------------------------------------------*/
11057 /* genGenPointerGet - gget value from generic pointer space */
11058 /*-----------------------------------------------------------------*/
11059 static void genGenPointerGet (operand *left,
11060 operand *result, iCode *ic)
11062 int size, offset, lit;
11063 sym_link *letype = getSpec(operandType(left));
11065 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11066 pic16_aopOp(left,ic,FALSE);
11067 pic16_aopOp(result,ic,TRUE);
11068 size = AOP_SIZE(result);
11070 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11072 /* if bit then unpack */
11073 if (IS_BITFIELD(letype)) {
11074 genUnpackBits(result,left,"BAD",GPOINTER);
11078 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11080 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11081 // load FSR0 from immediate
11082 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11084 werror(W_POSSBUG2, __FILE__, __LINE__);
11089 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11091 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11098 } else { /* we need to get it byte by byte */
11100 /* set up WREG:PRODL:FSR0L with address from left */
11101 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11102 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11103 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11105 pic16_callGenericPointerRW(0, size);
11107 assignResultValue(result, 1);
11113 pic16_freeAsmop(left,NULL,ic,TRUE);
11114 pic16_freeAsmop(result,NULL,ic,TRUE);
11117 /*-----------------------------------------------------------------*/
11118 /* genConstPointerGet - get value from const generic pointer space */
11119 /*-----------------------------------------------------------------*/
11120 static void genConstPointerGet (operand *left,
11121 operand *result, iCode *ic)
11123 //sym_link *retype = getSpec(operandType(result));
11124 // symbol *albl = newiTempLabel(NULL); // patch 15
11125 // symbol *blbl = newiTempLabel(NULL); //
11126 // PIC_OPCODE poc; // patch 15
11130 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11131 pic16_aopOp(left,ic,FALSE);
11132 pic16_aopOp(result,ic,TRUE);
11133 size = AOP_SIZE(result);
11135 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11137 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11139 // set up table pointer
11140 if( (AOP_TYPE(left) == AOP_PCODE)
11141 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11142 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11144 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11145 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11146 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11147 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11148 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11149 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11151 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11152 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11153 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11157 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11158 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11162 pic16_freeAsmop(left,NULL,ic,TRUE);
11163 pic16_freeAsmop(result,NULL,ic,TRUE);
11167 /*-----------------------------------------------------------------*/
11168 /* genPointerGet - generate code for pointer get */
11169 /*-----------------------------------------------------------------*/
11170 static void genPointerGet (iCode *ic)
11172 operand *left, *result ;
11173 sym_link *type, *etype;
11178 left = IC_LEFT(ic);
11179 result = IC_RESULT(ic) ;
11181 /* depending on the type of pointer we need to
11182 move it to the correct pointer register */
11183 type = operandType(left);
11184 etype = getSpec(type);
11187 if (IS_PTR_CONST(type))
11189 if (IS_CODEPTR(type))
11191 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11193 /* if left is of type of pointer then it is simple */
11194 if (IS_PTR(type) && !IS_FUNC(type->next))
11195 p_type = DCL_TYPE(type);
11197 /* we have to go by the storage class */
11198 p_type = PTR_TYPE(SPEC_OCLS(etype));
11200 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11202 if (SPEC_OCLS(etype)->codesp ) {
11203 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11204 //p_type = CPOINTER ;
11206 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11207 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11208 /*p_type = FPOINTER ;*/
11210 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11211 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11212 /* p_type = PPOINTER; */
11214 if (SPEC_OCLS(etype) == idata ) {
11215 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11216 /* p_type = IPOINTER; */
11218 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11219 /* p_type = POINTER ; */
11223 /* now that we have the pointer type we assign
11224 the pointer values */
11229 genNearPointerGet (left,result,ic);
11233 genPagedPointerGet(left,result,ic);
11237 /* PICs do not support FAR pointers... */
11238 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11240 genFarPointerGet (left,result,ic);
11245 genConstPointerGet (left,result,ic);
11246 //pic16_emitcodePointerGet (left,result,ic);
11251 if (IS_PTR_CONST(type))
11252 genConstPointerGet (left,result,ic);
11255 genGenPointerGet (left,result,ic);
11259 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11260 "genPointerGet: illegal pointer type");
11265 /*-----------------------------------------------------------------*/
11266 /* genPackBits - generates code for packed bit storage */
11267 /*-----------------------------------------------------------------*/
11268 static void genPackBits (sym_link *etype , operand *result,
11270 char *rname, int p_type)
11278 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11279 blen = SPEC_BLEN(etype);
11280 bstr = SPEC_BSTR(etype);
11282 retype = getSpec(operandType(right));
11284 if(AOP_TYPE(right) == AOP_LIT) {
11285 if((blen == 1) && (bstr < 8)) {
11287 /* it is a single bit, so use the appropriate bit instructions */
11289 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11291 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11292 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11293 if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11294 /* workaround to reduce the extra lfsr instruction */
11296 pic16_emitpcode(POC_BSF,
11297 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11299 pic16_emitpcode(POC_BCF,
11300 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11303 pic16_loadFSR0(result, 0);
11305 pic16_emitpcode(POC_BSF,
11306 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11308 pic16_emitpcode(POC_BCF,
11309 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11315 /* move literal to W */
11316 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11319 if(IS_BITFIELD(retype)
11320 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11324 rblen = SPEC_BLEN( retype );
11325 rbstr = SPEC_BSTR( retype );
11328 if(IS_BITFIELD(etype)) {
11329 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11330 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11332 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11335 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11337 if(IS_BITFIELD(etype)) {
11338 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11340 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11343 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11347 /* move right to W */
11348 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11351 /* if the bit length is less than or */
11352 /* it exactly fits a byte then */
11353 if((shCnt=SPEC_BSTR(etype))
11354 || SPEC_BLEN(etype) <= 8 ) {
11355 int fsr0_setup = 0;
11357 if (blen != 8 || bstr != 0) {
11358 // we need to combine the value with the old value
11359 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11361 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11362 SPEC_BSTR(etype), SPEC_BLEN(etype));
11364 /* shift left acc */
11367 /* using PRODH as a temporary register here */
11368 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11370 if (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) {
11371 /* access symbol directly */
11372 pic16_mov2w (AOP(result), 0);
11374 /* get old value */
11375 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11378 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11379 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11380 (unsigned char)(0xff >> (8-bstr))) ));
11381 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11382 } // if (blen != 8 || bstr != 0)
11384 /* write new value back */
11385 if (IS_SYMOP(result) & !IS_PTR(operandType(result))) {
11386 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11388 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11397 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11398 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11403 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11404 rLen = SPEC_BLEN(etype)-8;
11406 /* now generate for lengths greater than one byte */
11410 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11416 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11422 pic16_emitcode("movx","@dptr,a");
11427 DEBUGpic16_emitcode(";lcall","__gptrput");
11435 pic16_mov2w(AOP(right), offset++);
11438 /* last last was not complete */
11440 /* save the byte & read byte */
11443 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11444 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11449 pic16_emitcode ("mov","b,a");
11450 pic16_emitcode("movx","a,@dptr");
11454 pic16_emitcode ("push","b");
11455 pic16_emitcode ("push","acc");
11456 pic16_emitcode ("lcall","__gptrget");
11457 pic16_emitcode ("pop","b");
11463 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11464 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11465 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11466 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11467 // pic16_emitcode ("orl","a,b");
11470 // if (p_type == GPOINTER)
11471 // pic16_emitcode("pop","b");
11476 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11477 // pic16_emitcode("mov","@%s,a",rname);
11481 pic16_emitcode("movx","@dptr,a");
11485 DEBUGpic16_emitcode(";lcall","__gptrput");
11492 // pic16_freeAsmop(right, NULL, ic, TRUE);
11494 /*-----------------------------------------------------------------*/
11495 /* genDataPointerSet - remat pointer to data space */
11496 /*-----------------------------------------------------------------*/
11497 static void genDataPointerSet(operand *right,
11501 int size, offset = 0, resoffset=0 ;
11503 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11504 pic16_aopOp(right,ic,FALSE);
11506 size = AOP_SIZE(right);
11508 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11511 if ( AOP_TYPE(result) == AOP_PCODE) {
11512 fprintf(stderr,"genDataPointerSet %s, %d\n",
11513 AOP(result)->aopu.pcop->name,
11514 (AOP(result)->aopu.pcop->type == PO_DIR)?
11515 PCOR(AOP(result)->aopu.pcop)->instance:
11516 PCOI(AOP(result)->aopu.pcop)->offset);
11520 if(AOP(result)->aopu.pcop->type == PO_DIR)
11521 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11524 if (AOP_TYPE(right) == AOP_LIT) {
11527 if(!IS_FLOAT(operandType( right )))
11528 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11531 unsigned long lit_int;
11535 /* take care if literal is a float */
11536 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11537 lit = info.lit_int;
11540 lit = lit >> (8*offset);
11542 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11543 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11545 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11548 pic16_mov2w(AOP(right), offset);
11549 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11555 pic16_freeAsmop(right,NULL,ic,TRUE);
11560 /*-----------------------------------------------------------------*/
11561 /* genNearPointerSet - pic16_emitcode for near pointer put */
11562 /*-----------------------------------------------------------------*/
11563 static void genNearPointerSet (operand *right,
11569 sym_link *ptype = operandType(result);
11570 sym_link *resetype;
11572 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11573 retype= getSpec(operandType(right));
11574 resetype = getSpec(operandType(result));
11576 pic16_aopOp(result,ic,FALSE);
11578 /* if the result is rematerializable &
11579 * in data space & not a bit variable */
11581 /* and result is not a bit variable */
11582 if (AOP_TYPE(result) == AOP_PCODE
11583 // && AOP_TYPE(result) == AOP_IMMD
11584 && DCL_TYPE(ptype) == POINTER
11585 && !IS_BITFIELD(retype)
11586 && !IS_BITFIELD(resetype)) {
11588 genDataPointerSet (right,result,ic);
11589 pic16_freeAsmop(result,NULL,ic,TRUE);
11593 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11594 pic16_aopOp(right,ic,FALSE);
11595 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11597 /* if bitfield then unpack the bits */
11598 if (IS_BITFIELD(resetype)) {
11599 genPackBits (resetype, result, right, NULL, POINTER);
11601 /* we have can just get the values */
11602 int size = AOP_SIZE(right);
11605 pic16_loadFSR0(result, 0);
11607 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11609 if (AOP_TYPE(right) == AOP_LIT) {
11610 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11612 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11614 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11616 } else { // no literal
11618 pic16_emitpcode(POC_MOVFF,
11619 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11620 pic16_popCopyReg(&pic16_pc_postinc0)));
11622 pic16_emitpcode(POC_MOVFF,
11623 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11624 pic16_popCopyReg(&pic16_pc_indf0)));
11631 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11632 /* now some housekeeping stuff */
11634 /* we had to allocate for this iCode */
11635 pic16_freeAsmop(NULL,aop,ic,TRUE);
11637 /* we did not allocate which means left
11638 * already in a pointer register, then
11639 * if size > 0 && this could be used again
11640 * we have to point it back to where it
11642 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11643 if (AOP_SIZE(right) > 1
11644 && !OP_SYMBOL(result)->remat
11645 && ( OP_SYMBOL(result)->liveTo > ic->seq
11648 int size = AOP_SIZE(right) - 1;
11651 pic16_emitcode("decf","fsr0,f");
11652 //pic16_emitcode("dec","%s",rname);
11656 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11659 pic16_freeAsmop(right,NULL,ic,TRUE);
11660 pic16_freeAsmop(result,NULL,ic,TRUE);
11663 /*-----------------------------------------------------------------*/
11664 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11665 /*-----------------------------------------------------------------*/
11666 static void genPagedPointerSet (operand *right,
11671 regs *preg = NULL ;
11675 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11677 retype= getSpec(operandType(right));
11679 pic16_aopOp(result,ic,FALSE);
11681 /* if the value is already in a pointer register
11682 then don't need anything more */
11683 if (!AOP_INPREG(AOP(result))) {
11684 /* otherwise get a free pointer register */
11686 preg = getFreePtr(ic,&aop,FALSE);
11687 pic16_emitcode("mov","%s,%s",
11689 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11690 rname = preg->name ;
11692 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11694 pic16_freeAsmop(result,NULL,ic,TRUE);
11695 pic16_aopOp (right,ic,FALSE);
11697 /* if bitfield then unpack the bits */
11698 if (IS_BITFIELD(retype))
11699 genPackBits (retype,result,right,rname,PPOINTER);
11701 /* we have can just get the values */
11702 int size = AOP_SIZE(right);
11706 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11709 pic16_emitcode("movx","@%s,a",rname);
11712 pic16_emitcode("inc","%s",rname);
11718 /* now some housekeeping stuff */
11720 /* we had to allocate for this iCode */
11721 pic16_freeAsmop(NULL,aop,ic,TRUE);
11723 /* we did not allocate which means left
11724 already in a pointer register, then
11725 if size > 0 && this could be used again
11726 we have to point it back to where it
11728 if (AOP_SIZE(right) > 1 &&
11729 !OP_SYMBOL(result)->remat &&
11730 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11732 int size = AOP_SIZE(right) - 1;
11734 pic16_emitcode("dec","%s",rname);
11739 pic16_freeAsmop(right,NULL,ic,TRUE);
11745 /* This code is not adjusted to PIC16 and fails utterly...
11746 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11748 /*-----------------------------------------------------------------*/
11749 /* genFarPointerSet - set value from far space */
11750 /*-----------------------------------------------------------------*/
11751 static void genFarPointerSet (operand *right,
11752 operand *result, iCode *ic)
11755 sym_link *retype = getSpec(operandType(right));
11757 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11758 pic16_aopOp(result,ic,FALSE);
11760 /* if the operand is already in dptr
11761 then we do nothing else we move the value to dptr */
11762 if (AOP_TYPE(result) != AOP_STR) {
11763 /* if this is remateriazable */
11764 if (AOP_TYPE(result) == AOP_IMMD)
11765 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11766 else { /* we need to get it byte by byte */
11767 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11768 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11769 if (options.model == MODEL_FLAT24)
11771 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11775 /* so dptr know contains the address */
11776 pic16_freeAsmop(result,NULL,ic,TRUE);
11777 pic16_aopOp(right,ic,FALSE);
11779 /* if bit then unpack */
11780 if (IS_BITFIELD(retype))
11781 genPackBits(retype,result,right,"dptr",FPOINTER);
11783 size = AOP_SIZE(right);
11787 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11789 pic16_emitcode("movx","@dptr,a");
11791 pic16_emitcode("inc","dptr");
11795 pic16_freeAsmop(right,NULL,ic,TRUE);
11799 /*-----------------------------------------------------------------*/
11800 /* genGenPointerSet - set value from generic pointer space */
11801 /*-----------------------------------------------------------------*/
11803 static void genGenPointerSet (operand *right,
11804 operand *result, iCode *ic)
11806 int i, size, offset, lit;
11807 sym_link *retype = getSpec(operandType(right));
11809 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11811 pic16_aopOp(result,ic,FALSE);
11812 pic16_aopOp(right,ic,FALSE);
11813 size = AOP_SIZE(right);
11816 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11818 /* if the operand is already in dptr
11819 then we do nothing else we move the value to dptr */
11820 if (AOP_TYPE(result) != AOP_STR) {
11821 /* if this is remateriazable */
11822 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11823 // WARNING: anythig until "else" is untested!
11824 if (AOP_TYPE(result) == AOP_IMMD) {
11825 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11826 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11827 // load FSR0 from immediate
11828 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11832 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11834 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11840 else { /* we need to get it byte by byte */
11841 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11842 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11844 // set up FSR0 with address of result
11845 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11846 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11848 /* hack hack! see if this the FSR. If so don't load W */
11849 if(AOP_TYPE(right) != AOP_ACC) {
11851 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11853 if(AOP_TYPE(right) == AOP_LIT)
11856 // note: pic16_popGet handles sign extension
11857 for(i=0;i<size;i++) {
11858 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11860 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11862 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11867 for(i=0;i<size;i++) {
11869 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11870 pic16_popCopyReg(&pic16_pc_postinc0)));
11872 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11873 pic16_popCopyReg(&pic16_pc_indf0)));
11879 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11880 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11882 } // if (AOP_TYPE(result) != AOP_IMMD)
11884 } // if (AOP_TYPE(result) != AOP_STR)
11885 /* so dptr know contains the address */
11888 /* if bit then unpack */
11889 if (IS_BITFIELD(retype))
11890 genPackBits(retype,result,right,"dptr",GPOINTER);
11892 size = AOP_SIZE(right);
11895 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11897 // set up FSR0 with address of result
11898 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11899 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11902 if (AOP_TYPE(right) == AOP_LIT) {
11903 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11905 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11907 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11909 } else { // no literal
11911 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11913 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11921 pic16_freeAsmop(right,NULL,ic,TRUE);
11922 pic16_freeAsmop(result,NULL,ic,TRUE);
11926 static void genGenPointerSet (operand *right,
11927 operand *result, iCode *ic)
11930 sym_link *retype = getSpec(operandType(result));
11932 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11934 pic16_aopOp(result,ic,FALSE);
11935 pic16_aopOp(right,ic,FALSE);
11936 size = AOP_SIZE(right);
11938 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11941 /* if bit then unpack */
11942 if (IS_BITFIELD(retype)) {
11943 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11944 genPackBits(retype,result,right,"dptr",GPOINTER);
11948 size = AOP_SIZE(right);
11950 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11953 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11955 /* value of right+0 is placed on stack, which will be retrieved
11956 * by the support function this restoring the stack. The important
11957 * thing is that there is no need to manually restore stack pointer
11959 pushaop(AOP(right), 0);
11960 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11961 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11962 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11963 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
11965 /* load address to write to in WREG:FSR0H:FSR0L */
11966 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
11967 pic16_popCopyReg(&pic16_pc_fsr0l)));
11968 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
11969 pic16_popCopyReg(&pic16_pc_prodl)));
11970 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
11972 pic16_callGenericPointerRW(1, size);
11975 pic16_freeAsmop(right,NULL,ic,TRUE);
11976 pic16_freeAsmop(result,NULL,ic,TRUE);
11979 /*-----------------------------------------------------------------*/
11980 /* genPointerSet - stores the value into a pointer location */
11981 /*-----------------------------------------------------------------*/
11982 static void genPointerSet (iCode *ic)
11984 operand *right, *result ;
11985 sym_link *type, *etype;
11990 right = IC_RIGHT(ic);
11991 result = IC_RESULT(ic) ;
11993 /* depending on the type of pointer we need to
11994 move it to the correct pointer register */
11995 type = operandType(result);
11996 etype = getSpec(type);
11998 /* if left is of type of pointer then it is simple */
11999 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12000 p_type = DCL_TYPE(type);
12003 /* we have to go by the storage class */
12004 p_type = PTR_TYPE(SPEC_OCLS(etype));
12006 /* if (SPEC_OCLS(etype)->codesp ) { */
12007 /* p_type = CPOINTER ; */
12010 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12011 /* p_type = FPOINTER ; */
12013 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12014 /* p_type = PPOINTER ; */
12016 /* if (SPEC_OCLS(etype) == idata ) */
12017 /* p_type = IPOINTER ; */
12019 /* p_type = POINTER ; */
12022 /* now that we have the pointer type we assign
12023 the pointer values */
12028 genNearPointerSet (right,result,ic);
12032 genPagedPointerSet (right,result,ic);
12036 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12038 genFarPointerSet (right,result,ic);
12043 genGenPointerSet (right,result,ic);
12047 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12048 "genPointerSet: illegal pointer type");
12052 /*-----------------------------------------------------------------*/
12053 /* genIfx - generate code for Ifx statement */
12054 /*-----------------------------------------------------------------*/
12055 static void genIfx (iCode *ic, iCode *popIc)
12057 operand *cond = IC_COND(ic);
12062 pic16_aopOp(cond,ic,FALSE);
12064 /* get the value into acc */
12065 if (AOP_TYPE(cond) != AOP_CRY)
12066 pic16_toBoolean(cond);
12069 /* the result is now in the accumulator */
12070 pic16_freeAsmop(cond,NULL,ic,TRUE);
12072 /* if there was something to be popped then do it */
12076 /* if the condition is a bit variable */
12077 if (isbit && IS_ITEMP(cond) &&
12079 genIfxJump(ic,"c");
12080 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12082 if (isbit && !IS_ITEMP(cond))
12083 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12085 genIfxJump(ic,"a");
12090 /*-----------------------------------------------------------------*/
12091 /* genAddrOf - generates code for address of */
12092 /*-----------------------------------------------------------------*/
12093 static void genAddrOf (iCode *ic)
12095 operand *result, *left;
12097 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12098 pCodeOp *pcop0, *pcop1, *pcop2;
12102 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12104 sym = OP_SYMBOL( IC_LEFT(ic) );
12107 /* get address of symbol on stack */
12108 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12110 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12111 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12114 // operands on stack are accessible via "FSR2 + index" with index
12115 // starting at 2 for arguments and growing from 0 downwards for
12116 // local variables (index == 0 is not assigned so we add one here)
12118 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12120 assert (soffs < 0);
12123 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12124 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12125 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12126 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12127 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12128 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12129 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12135 // if(pic16_debug_verbose) {
12136 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12137 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12140 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12141 size = AOP_SIZE(IC_RESULT(ic));
12143 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12144 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12145 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12148 pic16_emitpcode(POC_MOVLW, pcop0);
12149 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12150 pic16_emitpcode(POC_MOVLW, pcop1);
12151 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12152 pic16_emitpcode(POC_MOVLW, pcop2);
12153 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12156 pic16_emitpcode(POC_MOVLW, pcop0);
12157 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12158 pic16_emitpcode(POC_MOVLW, pcop1);
12159 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12161 pic16_emitpcode(POC_MOVLW, pcop0);
12162 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12165 pic16_freeAsmop(left, NULL, ic, FALSE);
12167 pic16_freeAsmop(result,NULL,ic,TRUE);
12172 /*-----------------------------------------------------------------*/
12173 /* genFarFarAssign - assignment when both are in far space */
12174 /*-----------------------------------------------------------------*/
12175 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12177 int size = AOP_SIZE(right);
12180 /* first push the right side on to the stack */
12182 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12184 pic16_emitcode ("push","acc");
12187 pic16_freeAsmop(right,NULL,ic,FALSE);
12188 /* now assign DPTR to result */
12189 pic16_aopOp(result,ic,FALSE);
12190 size = AOP_SIZE(result);
12192 pic16_emitcode ("pop","acc");
12193 pic16_aopPut(AOP(result),"a",--offset);
12195 pic16_freeAsmop(result,NULL,ic,FALSE);
12200 /*-----------------------------------------------------------------*/
12201 /* genAssign - generate code for assignment */
12202 /*-----------------------------------------------------------------*/
12203 static void genAssign (iCode *ic)
12205 operand *result, *right;
12206 int size, offset,know_W;
12207 unsigned long lit = 0L;
12209 result = IC_RESULT(ic);
12210 right = IC_RIGHT(ic) ;
12214 /* if they are the same */
12215 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12218 /* reversed order operands are aopOp'ed so that result operand
12219 * is effective in case right is a stack symbol. This maneauver
12220 * allows to use the _G.resDirect flag later */
12221 pic16_aopOp(result,ic,TRUE);
12222 pic16_aopOp(right,ic,FALSE);
12224 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12226 /* if they are the same registers */
12227 if (pic16_sameRegs(AOP(right),AOP(result)))
12230 /* if the result is a bit */
12231 if (AOP_TYPE(result) == AOP_CRY) {
12232 /* if the right size is a literal then
12233 we know what the value is */
12234 if (AOP_TYPE(right) == AOP_LIT) {
12236 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12237 pic16_popGet(AOP(result),0));
12239 if (((int) operandLitValue(right)))
12240 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12241 AOP(result)->aopu.aop_dir,
12242 AOP(result)->aopu.aop_dir);
12244 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12245 AOP(result)->aopu.aop_dir,
12246 AOP(result)->aopu.aop_dir);
12250 /* the right is also a bit variable */
12251 if (AOP_TYPE(right) == AOP_CRY) {
12252 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12253 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12254 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12256 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12257 AOP(result)->aopu.aop_dir,
12258 AOP(result)->aopu.aop_dir);
12259 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12260 AOP(right)->aopu.aop_dir,
12261 AOP(right)->aopu.aop_dir);
12262 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12263 AOP(result)->aopu.aop_dir,
12264 AOP(result)->aopu.aop_dir);
12268 /* we need to or */
12269 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12270 pic16_toBoolean(right);
12272 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12273 //pic16_aopPut(AOP(result),"a",0);
12277 /* bit variables done */
12279 size = AOP_SIZE(result);
12282 if(AOP_TYPE(right) == AOP_LIT) {
12283 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12284 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12287 unsigned long lit_int;
12292 if(IS_FIXED16X16(operandType(right))) {
12293 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12295 /* take care if literal is a float */
12296 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12297 lit = info.lit_int;
12302 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12303 // sizeof(unsigned long int), sizeof(float));
12306 if (AOP_TYPE(right) == AOP_REG) {
12307 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12309 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12314 /* when do we have to read the program memory?
12315 * - if right itself is a symbol in code space
12316 * (we don't care what it points to if it's a pointer)
12317 * - AND right is not a function (we would want its address)
12319 if(AOP_TYPE(right) != AOP_LIT
12320 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12321 && !IS_FUNC(OP_SYM_TYPE(right))
12322 && !IS_ITEMP(right))
12324 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12325 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12327 // set up table pointer
12328 if(is_LitOp(right)) {
12329 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12330 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12331 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12332 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12333 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12334 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12335 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12337 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12338 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12339 pic16_popCopyReg(&pic16_pc_tblptrl)));
12340 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12341 pic16_popCopyReg(&pic16_pc_tblptrh)));
12342 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12343 pic16_popCopyReg(&pic16_pc_tblptru)));
12346 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12347 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12349 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12350 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12351 pic16_popGet(AOP(result),offset)));
12355 /* FIXME: for pointers we need to extend differently (according
12356 * to pointer type DATA/CODE/EEPROM/... :*/
12357 size = getSize(OP_SYM_TYPE(right));
12358 if(AOP_SIZE(result) > size) {
12359 size = AOP_SIZE(result) - size;
12361 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12371 /* VR - What is this?! */
12372 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12373 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12374 if(aopIdx(AOP(result),0) == 4) {
12376 /* this is a workaround to save value of right into wreg too,
12377 * value of wreg is going to be used later */
12378 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12379 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12380 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12384 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12390 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12391 if(AOP_TYPE(right) == AOP_LIT) {
12393 if(know_W != (lit&0xff))
12394 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12396 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12398 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12402 } else if (AOP_TYPE(right) == AOP_CRY) {
12403 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12405 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12406 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12407 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12409 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12410 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12411 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12413 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12415 if(!_G.resDirect) /* use this aopForSym feature */
12416 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12423 pic16_freeAsmop (right,NULL,ic,FALSE);
12424 pic16_freeAsmop (result,NULL,ic,TRUE);
12427 /*-----------------------------------------------------------------*/
12428 /* genJumpTab - generates code for jump table */
12429 /*-----------------------------------------------------------------*/
12430 static void genJumpTab (iCode *ic)
12435 pCodeOp *jt_offs_hi;
12440 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12441 /* get the condition into accumulator */
12442 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12444 /* multiply by three */
12445 pic16_emitcode("add","a,acc");
12446 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12448 jtab = newiTempLabel(NULL);
12449 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12450 pic16_emitcode("jmp","@a+dptr");
12451 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12454 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12455 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12457 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12458 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12459 pic16_emitpLabel(jtab->key);
12463 jt_offs = pic16_popGetTempReg(0);
12464 jt_offs_hi = pic16_popGetTempReg(1);
12465 jt_label = pic16_popGetLabel (jtab->key);
12466 //fprintf (stderr, "Creating jump table...\n");
12468 // calculate offset into jump table (idx * sizeof (GOTO))
12469 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12470 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12471 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12472 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12473 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12474 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12475 pic16_emitpcode(POC_MOVWF , jt_offs);
12477 // prepare PCLATx (set to first entry in jump table)
12478 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12479 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12480 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12481 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12482 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12484 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12485 pic16_emitpcode(POC_ADDWF , jt_offs);
12486 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12487 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12489 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12491 // release temporaries and prepare jump into table (new PCL --> WREG)
12492 pic16_emitpcode(POC_MOVFW , jt_offs);
12493 pic16_popReleaseTempReg (jt_offs_hi, 1);
12494 pic16_popReleaseTempReg (jt_offs, 0);
12496 // jump into the table
12497 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12499 pic16_emitpLabelFORCE(jtab->key);
12502 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12503 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12505 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12506 /* now generate the jump labels */
12507 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12508 jtab = setNextItem(IC_JTLABELS(ic))) {
12509 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12510 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12513 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12517 /*-----------------------------------------------------------------*/
12518 /* genMixedOperation - gen code for operators between mixed types */
12519 /*-----------------------------------------------------------------*/
12521 TSD - Written for the PIC port - but this unfortunately is buggy.
12522 This routine is good in that it is able to efficiently promote
12523 types to different (larger) sizes. Unfortunately, the temporary
12524 variables that are optimized out by this routine are sometimes
12525 used in other places. So until I know how to really parse the
12526 iCode tree, I'm going to not be using this routine :(.
12528 static int genMixedOperation (iCode *ic)
12531 operand *result = IC_RESULT(ic);
12532 sym_link *ctype = operandType(IC_LEFT(ic));
12533 operand *right = IC_RIGHT(ic);
12539 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12541 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12547 nextright = IC_RIGHT(nextic);
12548 nextleft = IC_LEFT(nextic);
12549 nextresult = IC_RESULT(nextic);
12551 pic16_aopOp(right,ic,FALSE);
12552 pic16_aopOp(result,ic,FALSE);
12553 pic16_aopOp(nextright, nextic, FALSE);
12554 pic16_aopOp(nextleft, nextic, FALSE);
12555 pic16_aopOp(nextresult, nextic, FALSE);
12557 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12559 operand *t = right;
12563 pic16_emitcode(";remove right +","");
12565 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12567 operand *t = right;
12571 pic16_emitcode(";remove left +","");
12575 big = AOP_SIZE(nextleft);
12576 small = AOP_SIZE(nextright);
12578 switch(nextic->op) {
12581 pic16_emitcode(";optimize a +","");
12582 /* if unsigned or not an integral type */
12583 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12584 pic16_emitcode(";add a bit to something","");
12587 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12589 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12590 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12591 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12593 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12601 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12602 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12603 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12606 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12608 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12609 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12610 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12611 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12612 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12615 pic16_emitcode("rlf","known_zero,w");
12622 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12623 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12624 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12626 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12636 pic16_freeAsmop(right,NULL,ic,TRUE);
12637 pic16_freeAsmop(result,NULL,ic,TRUE);
12638 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12639 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12641 nextic->generated = 1;
12648 /*-----------------------------------------------------------------*/
12649 /* genCast - gen code for casting */
12650 /*-----------------------------------------------------------------*/
12651 static void genCast (iCode *ic)
12653 operand *result = IC_RESULT(ic);
12654 sym_link *ctype = operandType(IC_LEFT(ic));
12655 sym_link *rtype = operandType(IC_RIGHT(ic));
12656 sym_link *restype = operandType(IC_RESULT(ic));
12657 operand *right = IC_RIGHT(ic);
12663 /* if they are equivalent then do nothing */
12664 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12667 pic16_aopOp(result,ic,FALSE);
12668 pic16_aopOp(right,ic,FALSE) ;
12670 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12673 /* if the result is a bit */
12674 if (AOP_TYPE(result) == AOP_CRY) {
12676 /* if the right size is a literal then
12677 * we know what the value is */
12678 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12680 if (AOP_TYPE(right) == AOP_LIT) {
12681 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12682 pic16_popGet(AOP(result),0));
12684 if (((int) operandLitValue(right)))
12685 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12686 AOP(result)->aopu.aop_dir,
12687 AOP(result)->aopu.aop_dir);
12689 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12690 AOP(result)->aopu.aop_dir,
12691 AOP(result)->aopu.aop_dir);
12695 /* the right is also a bit variable */
12696 if (AOP_TYPE(right) == AOP_CRY) {
12698 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12700 pic16_emitcode("clrc","");
12701 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12702 AOP(right)->aopu.aop_dir,
12703 AOP(right)->aopu.aop_dir);
12704 pic16_aopPut(AOP(result),"c",0);
12708 /* we need to or */
12709 if (AOP_TYPE(right) == AOP_REG) {
12710 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12711 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12712 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12714 pic16_toBoolean(right);
12715 pic16_aopPut(AOP(result),"a",0);
12719 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12722 size = AOP_SIZE(result);
12724 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12726 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12727 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12728 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12731 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12736 if(IS_BITFIELD(getSpec(restype))
12737 && IS_BITFIELD(getSpec(rtype))) {
12738 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12741 /* if they are the same size : or less */
12742 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12744 /* if they are in the same place */
12745 if (pic16_sameRegs(AOP(right),AOP(result)))
12748 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12750 if (IS_PTR_CONST(rtype))
12752 if (IS_CODEPTR(rtype))
12754 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12757 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12759 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12761 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12764 if(AOP_TYPE(right) == AOP_IMMD) {
12765 pCodeOp *pcop0, *pcop1, *pcop2;
12766 symbol *sym = OP_SYMBOL( right );
12768 size = AOP_SIZE(result);
12770 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12772 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12774 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12777 pic16_emitpcode(POC_MOVLW, pcop0);
12778 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12779 pic16_emitpcode(POC_MOVLW, pcop1);
12780 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12781 pic16_emitpcode(POC_MOVLW, pcop2);
12782 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12785 pic16_emitpcode(POC_MOVLW, pcop0);
12786 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12787 pic16_emitpcode(POC_MOVLW, pcop1);
12788 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12790 pic16_emitpcode(POC_MOVLW, pcop0);
12791 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12795 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12796 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12797 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12798 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12799 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12800 if(AOP_SIZE(result) <2)
12801 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12803 /* if they in different places then copy */
12804 size = AOP_SIZE(result);
12807 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12808 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12815 /* if the result is of type pointer */
12816 if (IS_PTR(ctype)) {
12818 sym_link *type = operandType(right);
12819 sym_link *etype = getSpec(type);
12821 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12823 /* pointer to generic pointer */
12824 if (IS_GENPTR(ctype)) {
12828 p_type = DCL_TYPE(type);
12830 /* we have to go by the storage class */
12831 p_type = PTR_TYPE(SPEC_OCLS(etype));
12833 /* if (SPEC_OCLS(etype)->codesp ) */
12834 /* p_type = CPOINTER ; */
12836 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12837 /* p_type = FPOINTER ; */
12839 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12840 /* p_type = PPOINTER; */
12842 /* if (SPEC_OCLS(etype) == idata ) */
12843 /* p_type = IPOINTER ; */
12845 /* p_type = POINTER ; */
12848 /* the first two bytes are known */
12849 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
12850 size = GPTRSIZE - 1;
12853 if(offset < AOP_SIZE(right)) {
12854 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12855 pic16_mov2f(AOP(result), AOP(right), offset);
12857 if ((AOP_TYPE(right) == AOP_PCODE) &&
12858 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12859 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12860 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12863 pic16_aopPut(AOP(result),
12864 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12869 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12872 /* the last byte depending on type */
12876 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12877 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12878 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12882 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12886 pic16_emitcode(";BUG!? ","%d",__LINE__);
12890 pic16_emitcode(";BUG!? ","%d",__LINE__);
12895 if (GPTRSIZE > AOP_SIZE(right)) {
12896 // assume data pointer... THIS MIGHT BE WRONG!
12897 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12898 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12900 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12905 /* this should never happen */
12906 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12907 "got unknown pointer type");
12910 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
12916 /* just copy the pointers */
12917 size = AOP_SIZE(result);
12920 pic16_aopPut(AOP(result),
12921 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12930 /* so we now know that the size of destination is greater
12931 than the size of the source.
12932 Now, if the next iCode is an operator then we might be
12933 able to optimize the operation without performing a cast.
12935 if(genMixedOperation(ic))
12938 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12940 /* we move to result for the size of source */
12941 size = AOP_SIZE(right);
12946 pic16_mov2f(AOP(result), AOP(right), offset);
12950 /* now depending on the sign of the destination */
12951 size = AOP_SIZE(result) - AOP_SIZE(right);
12952 /* if unsigned or not an integral type */
12953 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
12955 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12957 /* we need to extend the sign :( */
12960 /* Save one instruction of casting char to int */
12961 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12962 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12963 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
12965 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
12968 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12970 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12972 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
12975 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
12980 pic16_freeAsmop(right,NULL,ic,TRUE);
12981 pic16_freeAsmop(result,NULL,ic,TRUE);
12985 /*-----------------------------------------------------------------*/
12986 /* genDjnz - generate decrement & jump if not zero instrucion */
12987 /*-----------------------------------------------------------------*/
12988 static int genDjnz (iCode *ic, iCode *ifx)
12990 symbol *lbl, *lbl1;
12991 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12996 /* if the if condition has a false label
12997 then we cannot save */
13001 /* if the minus is not of the form
13003 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13004 !IS_OP_LITERAL(IC_RIGHT(ic)))
13007 if (operandLitValue(IC_RIGHT(ic)) != 1)
13010 /* if the size of this greater than one then no
13012 if (getSize(operandType(IC_RESULT(ic))) > 1)
13015 /* otherwise we can save BIG */
13016 lbl = newiTempLabel(NULL);
13017 lbl1= newiTempLabel(NULL);
13019 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13021 if (IS_AOP_PREG(IC_RESULT(ic))) {
13022 pic16_emitcode("dec","%s",
13023 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13024 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13025 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13029 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13030 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13032 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13033 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13037 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13038 ifx->generated = 1;
13042 /*-----------------------------------------------------------------*/
13043 /* genReceive - generate code for a receive iCode */
13044 /*-----------------------------------------------------------------*/
13045 static void genReceive (iCode *ic)
13051 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13052 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13054 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13056 if (isOperandInFarSpace(IC_RESULT(ic))
13057 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13058 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13060 int size = getSize(operandType(IC_RESULT(ic)));
13061 int offset = pic16_fReturnSizePic - size;
13065 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13066 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13070 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13072 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13073 size = AOP_SIZE(IC_RESULT(ic));
13076 pic16_emitcode ("pop","acc");
13077 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13080 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13082 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13085 /* set pseudo stack pointer to where it should be - dw*/
13086 GpsuedoStkPtr = ic->parmBytes;
13088 /* setting GpsuedoStkPtr has side effects here: */
13089 assignResultValue(IC_RESULT(ic), 0);
13092 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13095 /*-----------------------------------------------------------------*/
13096 /* genDummyRead - generate code for dummy read of volatiles */
13097 /*-----------------------------------------------------------------*/
13099 genDummyRead (iCode * ic)
13105 if (op && IS_SYMOP(op)) {
13106 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13107 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13110 pic16_aopOp (op, ic, FALSE);
13111 for (i=0; i < AOP_SIZE(op); i++) {
13112 // may need to protect this from the peepholer -- this is not nice but works...
13113 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13114 pic16_mov2w (AOP(op),i);
13115 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13117 pic16_freeAsmop (op, NULL, ic, TRUE);
13119 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13123 /*-----------------------------------------------------------------*/
13124 /* genpic16Code - generate code for pic16 based controllers */
13125 /*-----------------------------------------------------------------*/
13127 * At this point, ralloc.c has gone through the iCode and attempted
13128 * to optimize in a way suitable for a PIC. Now we've got to generate
13129 * PIC instructions that correspond to the iCode.
13131 * Once the instructions are generated, we'll pass through both the
13132 * peep hole optimizer and the pCode optimizer.
13133 *-----------------------------------------------------------------*/
13135 void genpic16Code (iCode *lic)
13140 lineHead = lineCurr = NULL;
13142 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13143 pic16_addpBlock(pb);
13146 /* if debug information required */
13147 if (options.debug && currFunc) {
13149 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13154 for (ic = lic ; ic ; ic = ic->next ) {
13156 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13157 if ( cln != ic->lineno ) {
13158 if ( options.debug ) {
13159 debugFile->writeCLine (ic);
13162 if(!options.noCcodeInAsm) {
13163 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13164 printCLine(ic->filename, ic->lineno)));
13170 if(options.iCodeInAsm) {
13173 /* insert here code to print iCode as comment */
13174 l = Safe_strdup(printILine(ic));
13175 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13178 /* if the result is marked as
13179 * spilt and rematerializable or code for
13180 * this has already been generated then
13182 if (resultRemat(ic) || ic->generated )
13185 /* depending on the operation */
13204 /* IPOP happens only when trying to restore a
13205 * spilt live range, if there is an ifx statement
13206 * following this pop then the if statement might
13207 * be using some of the registers being popped which
13208 * would destroy the contents of the register so
13209 * we need to check for this condition and handle it */
13211 && ic->next->op == IFX
13212 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13213 genIfx (ic->next,ic);
13231 genEndFunction (ic);
13247 pic16_genPlus (ic) ;
13251 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13252 pic16_genMinus (ic);
13268 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13272 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13278 /* note these two are xlated by algebraic equivalence
13279 * during parsing SDCC.y */
13280 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13281 "got '>=' or '<=' shouldn't have come here");
13285 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13297 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13301 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13305 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13329 genRightShift (ic);
13332 case GET_VALUE_AT_ADDRESS:
13337 if (POINTER_SET(ic))
13364 addSet(&_G.sendSet,ic);
13367 case DUMMY_READ_VOLATILE:
13377 /* now we are ready to call the
13378 peep hole optimizer */
13379 if (!options.nopeep)
13380 peepHole (&lineHead);
13382 /* now do the actual printing */
13383 printLine (lineHead, codeOutFile);
13386 DFPRINTF((stderr,"printing pBlock\n\n"));
13387 pic16_printpBlock(stdout,pb);