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];
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];
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];
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++));
2682 #if !defined(GEN_Not)
2683 /*-----------------------------------------------------------------*/
2684 /* genNot - generate code for ! operation */
2685 /*-----------------------------------------------------------------*/
2686 static void pic16_genNot (iCode *ic)
2692 /* assign asmOps to operand & result */
2693 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2694 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2696 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2697 /* if in bit space then a special case */
2698 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2699 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2700 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2701 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2703 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2704 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2705 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2710 size = AOP_SIZE(IC_LEFT(ic));
2712 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2713 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2714 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2717 pic16_toBoolean(IC_LEFT(ic));
2719 tlbl = newiTempLabel(NULL);
2720 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2721 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2722 pic16_outBitC(IC_RESULT(ic));
2725 /* release the aops */
2726 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2727 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2732 #if !defined(GEN_Cpl)
2733 /*-----------------------------------------------------------------*/
2734 /* genCpl - generate code for complement */
2735 /*-----------------------------------------------------------------*/
2736 static void pic16_genCpl (iCode *ic)
2742 /* assign asmOps to operand & result */
2743 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2744 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2746 /* if both are in bit space then
2748 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2749 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2751 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2752 pic16_emitcode("cpl","c");
2753 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2757 size = AOP_SIZE(IC_RESULT(ic));
2760 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2762 pic16_emitcode("cpl","a");
2763 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2765 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2766 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2768 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2769 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2777 /* release the aops */
2778 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2779 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2783 /*-----------------------------------------------------------------*/
2784 /* genUminusFloat - unary minus for floating points */
2785 /*-----------------------------------------------------------------*/
2786 static void genUminusFloat(operand *op,operand *result)
2788 int size ,offset =0 ;
2791 /* for this we just need to flip the
2792 first it then copy the rest in place */
2793 size = AOP_SIZE(op);
2796 pic16_mov2f(AOP(result), AOP(op), offset);
2800 /* toggle the MSB's highest bit */
2801 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2804 /*-----------------------------------------------------------------*/
2805 /* genUminus - unary minus code generation */
2806 /*-----------------------------------------------------------------*/
2807 static void genUminus (iCode *ic)
2810 sym_link *optype, *rtype;
2817 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2818 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2820 /* if both in bit space then special case */
2821 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2822 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2824 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2825 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2826 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2830 optype = operandType(IC_LEFT(ic));
2831 rtype = operandType(IC_RESULT(ic));
2833 /* if float then do float stuff */
2834 if (IS_FLOAT(optype)) {
2835 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2839 /* otherwise subtract from zero by taking the 2's complement */
2840 size = AOP_SIZE(IC_LEFT(ic));
2841 label = newiTempLabel ( NULL );
2843 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2844 for (i=size-1; i > 0; i--) {
2845 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2847 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2848 for (i=1; i < size; i++) {
2849 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2850 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2853 for (i=size-1; i >= 0; i--) {
2854 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2855 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2858 for (i=0; i < size-2; i++) {
2859 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2860 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2862 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2864 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2867 pic16_emitpLabel (label->key);
2870 /* release the aops */
2871 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2872 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2876 /*-----------------------------------------------------------------*/
2877 /* saveRegisters - will look for a call and save the registers */
2878 /*-----------------------------------------------------------------*/
2879 static void saveRegisters(iCode *lic)
2886 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2888 for (ic = lic ; ic ; ic = ic->next)
2889 if (ic->op == CALL || ic->op == PCALL)
2893 fprintf(stderr,"found parameter push with no function call\n");
2897 /* if the registers have been saved already then
2899 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2902 /* find the registers in use at this time
2903 and push them away to safety */
2904 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2908 if (options.useXstack) {
2909 if (bitVectBitValue(rsave,R0_IDX))
2910 pic16_emitcode("mov","b,r0");
2911 pic16_emitcode("mov","r0,%s",spname);
2912 for (i = 0 ; i < pic16_nRegs ; i++) {
2913 if (bitVectBitValue(rsave,i)) {
2915 pic16_emitcode("mov","a,b");
2917 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2918 pic16_emitcode("movx","@r0,a");
2919 pic16_emitcode("inc","r0");
2922 pic16_emitcode("mov","%s,r0",spname);
2923 if (bitVectBitValue(rsave,R0_IDX))
2924 pic16_emitcode("mov","r0,b");
2926 //for (i = 0 ; i < pic16_nRegs ; i++) {
2927 // if (bitVectBitValue(rsave,i))
2928 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2931 dtype = operandType(IC_LEFT(ic));
2932 if (currFunc && dtype &&
2933 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2934 IFFUNC_ISISR(currFunc->type) &&
2937 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2940 /*-----------------------------------------------------------------*/
2941 /* unsaveRegisters - pop the pushed registers */
2942 /*-----------------------------------------------------------------*/
2943 static void unsaveRegisters (iCode *ic)
2948 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2949 /* find the registers in use at this time
2950 and push them away to safety */
2951 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2954 if (options.useXstack) {
2955 pic16_emitcode("mov","r0,%s",spname);
2956 for (i = pic16_nRegs ; i >= 0 ; i--) {
2957 if (bitVectBitValue(rsave,i)) {
2958 pic16_emitcode("dec","r0");
2959 pic16_emitcode("movx","a,@r0");
2961 pic16_emitcode("mov","b,a");
2963 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2967 pic16_emitcode("mov","%s,r0",spname);
2968 if (bitVectBitValue(rsave,R0_IDX))
2969 pic16_emitcode("mov","r0,b");
2971 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2972 // if (bitVectBitValue(rsave,i))
2973 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2980 /*-----------------------------------------------------------------*/
2982 /*-----------------------------------------------------------------*/
2983 static void pushSide(operand * oper, int size)
2986 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2988 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2989 if (AOP_TYPE(oper) != AOP_REG &&
2990 AOP_TYPE(oper) != AOP_DIR &&
2992 pic16_emitcode("mov","a,%s",l);
2993 pic16_emitcode("push","acc");
2995 pic16_emitcode("push","%s",l);
3000 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
3002 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3003 pic16_emitpcode(POC_MOVFW, src);
3004 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
3006 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3007 src, pic16_popGet(AOP(op), offset)));
3012 /*-----------------------------------------------------------------*/
3013 /* assignResultValue - assign results to oper, rescall==1 is */
3014 /* called from genCall() or genPcall() */
3015 /*-----------------------------------------------------------------*/
3016 static void assignResultValue(operand * oper, int rescall)
3018 int size = AOP_SIZE(oper);
3022 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3023 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3026 /* assign result from a call/pcall function() */
3028 /* function results are stored in a special order,
3029 * see top of file with Function return policy, or manual */
3032 /* 8-bits, result in WREG */
3033 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3036 /* 16-bits, result in PRODL:WREG */
3037 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3041 /* 24-bits, result in PRODH:PRODL:WREG */
3042 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3046 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3047 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3051 /* >32-bits, result on stack, and FSR0 points to beginning.
3052 * Fix stack when done */
3054 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3056 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3057 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3059 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3064 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3065 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3066 if(STACK_MODEL_LARGE) {
3068 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3072 int areg = 0; /* matching argument register */
3074 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3075 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3078 /* its called from genReceive (probably) -- VR */
3079 /* I hope this code will not be called from somewhere else in the future!
3080 * We manually set the pseudo stack pointer in genReceive. - dw
3082 if(!GpsuedoStkPtr && _G.useWreg) {
3083 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3085 /* The last byte in the assignment is in W */
3086 if(areg <= GpsuedoStkPtr) {
3088 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3090 // debugf("receive from WREG\n", 0);
3092 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3095 _G.stack_lat = AOP_SIZE(oper)-1;
3100 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3101 // debugf("receive from STACK\n", 0);
3108 /*-----------------------------------------------------------------*/
3109 /* genIpush - generate code for pushing this gets a little complex */
3110 /*-----------------------------------------------------------------*/
3111 static void genIpush (iCode *ic)
3113 // int size, offset=0;
3116 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3119 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3121 /* send to stack as normal */
3122 addSet(&_G.sendSet,ic);
3123 // addSetHead(&_G.sendSet,ic);
3124 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3129 int size, offset = 0 ;
3133 /* if this is not a parm push : ie. it is spill push
3134 and spill push is always done on the local stack */
3135 if (!ic->parmPush) {
3137 /* and the item is spilt then do nothing */
3138 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3141 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3142 size = AOP_SIZE(IC_LEFT(ic));
3143 /* push it on the stack */
3145 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3150 pic16_emitcode("push","%s",l);
3155 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3159 /*-----------------------------------------------------------------*/
3160 /* genIpop - recover the registers: can happen only for spilling */
3161 /*-----------------------------------------------------------------*/
3162 static void genIpop (iCode *ic)
3165 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3170 /* if the temp was not pushed then */
3171 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3174 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3175 size = AOP_SIZE(IC_LEFT(ic));
3178 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3181 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3186 /*-----------------------------------------------------------------*/
3187 /* unsaverbank - restores the resgister bank from stack */
3188 /*-----------------------------------------------------------------*/
3189 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3191 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3197 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3199 if (options.useXstack) {
3201 r = getFreePtr(ic,&aop,FALSE);
3204 pic16_emitcode("mov","%s,_spx",r->name);
3205 pic16_emitcode("movx","a,@%s",r->name);
3206 pic16_emitcode("mov","psw,a");
3207 pic16_emitcode("dec","%s",r->name);
3210 pic16_emitcode ("pop","psw");
3213 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3214 if (options.useXstack) {
3215 pic16_emitcode("movx","a,@%s",r->name);
3216 //pic16_emitcode("mov","(%s+%d),a",
3217 // regspic16[i].base,8*bank+regspic16[i].offset);
3218 pic16_emitcode("dec","%s",r->name);
3221 pic16_emitcode("pop",""); //"(%s+%d)",
3222 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3225 if (options.useXstack) {
3227 pic16_emitcode("mov","_spx,%s",r->name);
3228 pic16_freeAsmop(NULL,aop,ic,TRUE);
3234 /*-----------------------------------------------------------------*/
3235 /* saverbank - saves an entire register bank on the stack */
3236 /*-----------------------------------------------------------------*/
3237 static void saverbank (int bank, iCode *ic, bool pushPsw)
3239 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3245 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3246 if (options.useXstack) {
3249 r = getFreePtr(ic,&aop,FALSE);
3250 pic16_emitcode("mov","%s,_spx",r->name);
3254 for (i = 0 ; i < pic16_nRegs ;i++) {
3255 if (options.useXstack) {
3256 pic16_emitcode("inc","%s",r->name);
3257 //pic16_emitcode("mov","a,(%s+%d)",
3258 // regspic16[i].base,8*bank+regspic16[i].offset);
3259 pic16_emitcode("movx","@%s,a",r->name);
3261 pic16_emitcode("push","");// "(%s+%d)",
3262 //regspic16[i].base,8*bank+regspic16[i].offset);
3266 if (options.useXstack) {
3267 pic16_emitcode("mov","a,psw");
3268 pic16_emitcode("movx","@%s,a",r->name);
3269 pic16_emitcode("inc","%s",r->name);
3270 pic16_emitcode("mov","_spx,%s",r->name);
3271 pic16_freeAsmop (NULL,aop,ic,TRUE);
3274 pic16_emitcode("push","psw");
3276 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3284 static int wparamCmp(void *p1, void *p2)
3286 return (!strcmp((char *)p1, (char *)p2));
3289 int inWparamList(char *s)
3291 return isinSetWith(wparamList, s, wparamCmp);
3295 /*-----------------------------------------------------------------*/
3296 /* genCall - generates a call statement */
3297 /*-----------------------------------------------------------------*/
3298 static void genCall (iCode *ic)
3308 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3309 /* if caller saves & we have not saved then */
3310 // if (!ic->regsSaved)
3311 // saveRegisters(ic);
3313 /* initialise stackParms for IPUSH pushes */
3314 // stackParms = psuedoStkPtr;
3315 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3316 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3317 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3320 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3323 /* if send set is not empty the assign */
3326 int psuedoStkPtr=-1;
3327 int firstTimeThruLoop = 1;
3330 /* reverse sendSet if function is not reentrant */
3331 if(!IFFUNC_ISREENT(ftype))
3332 _G.sendSet = reverseSet(_G.sendSet);
3334 /* First figure how many parameters are getting passed */
3338 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3342 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3343 size = AOP_SIZE(IC_LEFT(sic));
3347 /* pass the last byte through WREG */
3351 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3352 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3353 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3355 if(!firstTimeThruLoop) {
3356 /* If this is not the first time we've been through the loop
3357 * then we need to save the parameter in a temporary
3358 * register. The last byte of the last parameter is
3362 // --psuedoStkPtr; // sanity check
3366 firstTimeThruLoop=0;
3368 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3373 /* all arguments are passed via stack */
3377 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3378 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3379 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3381 // pushaop(AOP(IC_LEFT(sic)), size);
3382 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3389 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3393 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3394 pushw(); /* save last parameter to stack if functions has varargs */
3398 } else use_wreg = 0;
3400 _G.stackRegSet = _G.sendSet;
3405 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3409 /* if we need to assign a result value */
3410 if ((IS_ITEMP(IC_RESULT(ic))
3411 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3412 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3413 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3416 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3419 assignResultValue(IC_RESULT(ic), 1);
3421 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3422 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3424 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3427 if(!stackParms && ic->parmBytes) {
3428 stackParms = ic->parmBytes;
3431 stackParms -= use_wreg;
3434 if(stackParms == 1) {
3435 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3437 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3438 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3440 if(STACK_MODEL_LARGE) {
3442 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3447 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3450 /* adjust the stack for parameters if required */
3451 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3454 /* if register bank was saved then pop them */
3456 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3458 /* if we hade saved some registers then unsave them */
3459 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3460 unsaveRegisters (ic);
3466 /*-----------------------------------------------------------------*/
3467 /* genPcall - generates a call by pointer statement */
3468 /* new version, created from genCall - HJD */
3469 /*-----------------------------------------------------------------*/
3470 static void genPcall (iCode *ic)
3472 sym_link *ftype, *fntype;
3474 symbol *retlbl = newiTempLabel(NULL);
3475 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3479 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3480 fntype = operandType( IC_LEFT(ic) )->next;
3482 /* if send set is not empty the assign */
3485 int psuedoStkPtr=-1;
3487 /* reverse sendSet if function is not reentrant */
3488 if(!IFFUNC_ISREENT(fntype))
3489 _G.sendSet = reverseSet(_G.sendSet);
3493 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3496 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3497 size = AOP_SIZE(IC_LEFT(sic));
3500 /* all parameters are passed via stack, since WREG is clobbered
3501 * by the calling sequence */
3503 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3504 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3505 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3507 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3511 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3514 _G.stackRegSet = _G.sendSet;
3518 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3520 // push return address
3521 // push $ on return stack, then replace with retlbl
3523 /* Thanks to Thorsten Klose for pointing out that the following
3524 * snippet should be interrupt safe */
3525 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3526 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3528 pic16_emitpcodeNULLop(POC_PUSH);
3530 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3531 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3532 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3533 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3534 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3535 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3538 /* restore interrupt control register */
3539 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3540 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3542 /* make the call by writing the pointer into pc */
3543 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3544 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3546 // note: MOVFF to PCL not allowed
3547 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3548 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3551 /* return address is here: (X) */
3552 pic16_emitpLabelFORCE(retlbl->key);
3554 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3557 /* if we need assign a result value */
3558 if ((IS_ITEMP(IC_RESULT(ic))
3559 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3560 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3561 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3564 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3567 assignResultValue(IC_RESULT(ic), 1);
3569 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3570 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3572 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3575 // stackParms -= use_wreg;
3578 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3579 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3580 if(STACK_MODEL_LARGE) {
3582 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3587 /*-----------------------------------------------------------------*/
3588 /* resultRemat - result is rematerializable */
3589 /*-----------------------------------------------------------------*/
3590 static int resultRemat (iCode *ic)
3592 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3593 if (SKIP_IC(ic) || ic->op == IFX)
3596 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3597 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3598 if (sym->remat && !POINTER_SET(ic))
3605 #if defined(__BORLANDC__) || defined(_MSC_VER)
3606 #define STRCASECMP stricmp
3608 #define STRCASECMP strcasecmp
3612 /*-----------------------------------------------------------------*/
3613 /* inExcludeList - return 1 if the string is in exclude Reg list */
3614 /*-----------------------------------------------------------------*/
3615 static bool inExcludeList(char *s)
3617 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3620 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3621 if (options.excludeRegs[i] &&
3622 STRCASECMP(options.excludeRegs[i],"none") == 0)
3625 for ( i = 0 ; options.excludeRegs[i]; i++) {
3626 if (options.excludeRegs[i] &&
3627 STRCASECMP(s,options.excludeRegs[i]) == 0)
3634 /*-----------------------------------------------------------------*/
3635 /* genFunction - generated code for function entry */
3636 /*-----------------------------------------------------------------*/
3637 static void genFunction (iCode *ic)
3643 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3645 pic16_labelOffset += (max_key+4);
3650 ftype = operandType(IC_LEFT(ic));
3651 sym = OP_SYMBOL(IC_LEFT(ic));
3653 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3654 /* create an absolute section at the interrupt vector:
3655 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3660 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3662 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3663 sprintf(asymname, "ivec_%s", sym->name);
3665 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3667 /* when an interrupt is declared as naked, do not emit the special
3668 * wrapper segment at vector address. The user should take care for
3669 * this instead. -- VR */
3671 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3672 asym = newSymbol(asymname, 0);
3673 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3674 pic16_addpBlock( apb );
3676 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3677 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3678 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3679 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3680 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3682 /* mark the end of this tiny function */
3683 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3685 sprintf(asymname, "%s", sym->rname);
3691 abSym = Safe_calloc(1, sizeof(absSym));
3692 strcpy(abSym->name, asymname);
3694 switch( FUNC_INTNO(sym->type) ) {
3695 case 0: abSym->address = 0x000000; break;
3696 case 1: abSym->address = 0x000008; break;
3697 case 2: abSym->address = 0x000018; break;
3700 // fprintf(stderr, "no interrupt number is given\n");
3701 abSym->address = -1; break;
3704 /* relocate interrupt vectors if needed */
3705 if(abSym->address != -1)
3706 abSym->address += pic16_options.ivt_loc;
3708 addSet(&absSymSet, abSym);
3712 /* create the function header */
3713 pic16_emitcode(";","-----------------------------------------");
3714 pic16_emitcode(";"," function %s",sym->name);
3715 pic16_emitcode(";","-----------------------------------------");
3717 pic16_emitcode("","%s:",sym->rname);
3718 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3723 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3724 if(!strcmp(ab->name, sym->rname)) {
3725 pic16_pBlockConvert2Absolute(pb);
3731 if(IFFUNC_ISNAKED(ftype)) {
3732 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3736 /* if critical function then turn interrupts off */
3737 if (IFFUNC_ISCRITICAL(ftype)) {
3738 //pic16_emitcode("clr","ea");
3741 currFunc = sym; /* update the currFunc symbol */
3742 _G.fregsUsed = sym->regsUsed;
3743 _G.sregsAlloc = newBitVect(128);
3746 /* if this is an interrupt service routine then
3747 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3748 if (IFFUNC_ISISR(sym->type)) {
3749 _G.usefastretfie = 1; /* use shadow registers by default */
3751 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3752 if(!FUNC_ISSHADOWREGS(sym->type)) {
3753 /* do not save WREG,STATUS,BSR for high priority interrupts
3754 * because they are stored in the hardware shadow registers already */
3755 _G.usefastretfie = 0;
3756 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3757 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3758 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3761 /* these should really be optimized somehow, because not all
3762 * interrupt handlers modify them */
3763 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3764 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3765 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3766 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3768 // pic16_pBlockConvert2ISR(pb);
3771 /* emit code to setup stack frame if user enabled,
3772 * and function is not main() */
3774 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3775 if(strcmp(sym->name, "main")) {
3777 || !options.ommitFramePtr
3779 || IFFUNC_ARGS(sym->type)
3780 || FUNC_HASSTACKPARM(sym->etype)
3782 /* setup the stack frame */
3783 if(STACK_MODEL_LARGE)
3784 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3785 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3787 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3788 if(STACK_MODEL_LARGE)
3789 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3793 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3796 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3798 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3799 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3801 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3804 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3805 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3812 /* if callee-save to be used for this function
3813 * then save the registers being used in this function */
3814 // if (IFFUNC_CALLEESAVES(sym->type))
3818 /* if any registers used */
3819 if (sym->regsUsed) {
3820 /* save the registers used */
3821 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3822 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3823 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3824 if (bitVectBitValue(sym->regsUsed,i)) {
3825 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3828 if(!pic16_regWithIdx(i)->wasUsed) {
3829 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3830 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3831 pic16_regWithIdx(i)->wasUsed = 1;
3835 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3839 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3840 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3843 /*-----------------------------------------------------------------*/
3844 /* genEndFunction - generates epilogue for functions */
3845 /*-----------------------------------------------------------------*/
3846 static void genEndFunction (iCode *ic)
3848 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3852 if(IFFUNC_ISNAKED(sym->type)) {
3853 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3859 /* add code for ISCRITICAL */
3860 if(IFFUNC_ISCRITICAL(sym->type)) {
3861 /* if critical function, turn on interrupts */
3863 /* TODO: add code here -- VR */
3866 // sym->regsUsed = _G.fregsUsed;
3868 /* now we need to restore the registers */
3869 /* if any registers used */
3871 /* first restore registers that might be used for stack access */
3872 if(_G.sregsAllocSet) {
3875 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3876 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3877 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3881 if (sym->regsUsed) {
3884 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3885 /* restore registers used */
3886 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3887 for ( i = sym->regsUsed->size; i >= 0; i--) {
3888 if (bitVectBitValue(sym->regsUsed,i)) {
3889 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3893 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3898 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3900 if (sym->stack == 1) {
3901 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3902 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3904 // we have to add more than one...
3905 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3906 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3907 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3909 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3910 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3911 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3915 if(strcmp(sym->name, "main")) {
3917 || !options.ommitFramePtr
3919 || IFFUNC_ARGS(sym->type)
3920 || FUNC_HASSTACKPARM(sym->etype)
3922 /* restore stack frame */
3923 if(STACK_MODEL_LARGE)
3924 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3925 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3931 if (IFFUNC_ISISR(sym->type)) {
3932 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3933 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3934 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3935 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3937 if(!FUNC_ISSHADOWREGS(sym->type)) {
3938 /* do not restore interrupt vector for WREG,STATUS,BSR
3939 * for high priority interrupt, see genFunction */
3940 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3941 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3942 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3944 // _G.interruptvector = 0; /* sanity check */
3947 /* if debug then send end of function */
3948 /* if (options.debug && currFunc) */
3950 debugFile->writeEndFunction (currFunc, ic, 1);
3953 if(_G.usefastretfie)
3954 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3956 pic16_emitpcodeNULLop(POC_RETFIE);
3958 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3960 _G.usefastretfie = 0;
3964 if (IFFUNC_ISCRITICAL(sym->type)) {
3965 pic16_emitcode("setb","ea");
3968 /* if debug then send end of function */
3970 debugFile->writeEndFunction (currFunc, ic, 1);
3973 /* insert code to restore stack frame, if user enabled it
3974 * and function is not main() */
3977 pic16_emitpcodeNULLop(POC_RETURN);
3979 /* Mark the end of a function */
3980 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3984 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3986 unsigned long lit=1;
3991 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3992 if(AOP_TYPE(op) == AOP_LIT) {
3993 if(!IS_FLOAT(operandType( op ))) {
3994 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3997 unsigned long lit_int;
4001 /* take care if literal is a float */
4002 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4008 if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
4009 pic16_emitpcode(POC_CLRF, dest);
4011 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
4012 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
4015 if(dest->type == PO_WREG && (offset == 0)) {
4016 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4019 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4023 /*-----------------------------------------------------------------*/
4024 /* genRet - generate code for return statement */
4025 /*-----------------------------------------------------------------*/
4026 static void genRet (iCode *ic)
4032 /* if we have no return value then
4033 * just generate the "ret" */
4038 /* we have something to return then
4039 * move the return value into place */
4040 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4041 size = AOP_SIZE(IC_LEFT(ic));
4045 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4048 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4051 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4053 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4056 /* >32-bits, setup stack and FSR0 */
4058 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4059 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4061 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4063 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4068 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4069 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4071 if(STACK_MODEL_LARGE) {
4072 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4073 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4075 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4080 /* old code, left here for reference -- VR */
4084 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4086 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4087 pic16_emitpcomment("push %s",l);
4090 DEBUGpic16_emitcode(";", "%d", __LINE__);
4091 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4092 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4094 if (strcmp(fReturn[offset],l)) {
4095 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4096 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4097 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4099 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4103 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4113 if (strcmp(fReturn[pushed],"a"))
4114 pic16_emitcode("pop",fReturn[pushed]);
4116 pic16_emitcode("pop","acc");
4122 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4125 /* generate a jump to the return label
4126 * if the next is not the return statement */
4127 if (!(ic->next && ic->next->op == LABEL
4128 && IC_LABEL(ic->next) == returnLabel)) {
4130 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4131 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4135 /*-----------------------------------------------------------------*/
4136 /* genLabel - generates a label */
4137 /*-----------------------------------------------------------------*/
4138 static void genLabel (iCode *ic)
4142 /* special case never generate */
4143 if (IC_LABEL(ic) == entryLabel)
4146 pic16_emitpLabel(IC_LABEL(ic)->key);
4147 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4150 /*-----------------------------------------------------------------*/
4151 /* genGoto - generates a goto */
4152 /*-----------------------------------------------------------------*/
4154 static void genGoto (iCode *ic)
4157 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4158 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4162 /*-----------------------------------------------------------------*/
4163 /* genMultbits :- multiplication of bits */
4164 /*-----------------------------------------------------------------*/
4165 static void genMultbits (operand *left,
4171 if(!pic16_sameRegs(AOP(result),AOP(right)))
4172 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4174 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4175 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4176 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4181 /*-----------------------------------------------------------------*/
4182 /* genMultOneByte : 8 bit multiplication & division */
4183 /*-----------------------------------------------------------------*/
4184 static void genMultOneByte (operand *left,
4190 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4191 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4193 /* (if two literals, the value is computed before) */
4194 /* if one literal, literal on the right */
4195 if (AOP_TYPE(left) == AOP_LIT){
4201 /* size is already checked in genMult == 1 */
4202 // size = AOP_SIZE(result);
4204 if (AOP_TYPE(right) == AOP_LIT){
4205 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4206 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4207 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4208 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4210 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4211 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4212 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4213 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4216 pic16_genMult8X8_8 (left, right,result);
4219 /*-----------------------------------------------------------------*/
4220 /* genMultOneWord : 16 bit multiplication */
4221 /*-----------------------------------------------------------------*/
4222 static void genMultOneWord (operand *left,
4227 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4228 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4230 /* (if two literals, the value is computed before)
4231 * if one literal, literal on the right */
4232 if (AOP_TYPE(left) == AOP_LIT){
4238 /* size is checked already == 2 */
4239 // size = AOP_SIZE(result);
4241 if (AOP_TYPE(right) == AOP_LIT) {
4242 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4243 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4244 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4245 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4247 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4248 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4249 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4250 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4253 pic16_genMult16X16_16(left, right,result);
4256 /*-----------------------------------------------------------------*/
4257 /* genMultOneLong : 32 bit multiplication */
4258 /*-----------------------------------------------------------------*/
4259 static void genMultOneLong (operand *left,
4264 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4265 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4267 /* (if two literals, the value is computed before)
4268 * if one literal, literal on the right */
4269 if (AOP_TYPE(left) == AOP_LIT){
4275 /* size is checked already == 4 */
4276 // size = AOP_SIZE(result);
4278 if (AOP_TYPE(right) == AOP_LIT) {
4279 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4280 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4281 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4282 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4284 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4285 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4286 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4287 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4290 pic16_genMult32X32_32(left, right,result);
4295 /*-----------------------------------------------------------------*/
4296 /* genMult - generates code for multiplication */
4297 /*-----------------------------------------------------------------*/
4298 static void genMult (iCode *ic)
4300 operand *left = IC_LEFT(ic);
4301 operand *right = IC_RIGHT(ic);
4302 operand *result= IC_RESULT(ic);
4305 /* assign the amsops */
4306 pic16_aopOp (left,ic,FALSE);
4307 pic16_aopOp (right,ic,FALSE);
4308 pic16_aopOp (result,ic,TRUE);
4310 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4312 /* special cases first *
4314 if (AOP_TYPE(left) == AOP_CRY
4315 && AOP_TYPE(right)== AOP_CRY) {
4316 genMultbits(left,right,result);
4320 /* if both are of size == 1 */
4321 if(AOP_SIZE(left) == 1
4322 && AOP_SIZE(right) == 1) {
4323 genMultOneByte(left,right,result);
4327 /* if both are of size == 2 */
4328 if(AOP_SIZE(left) == 2
4329 && AOP_SIZE(right) == 2) {
4330 genMultOneWord(left, right, result);
4334 /* if both are of size == 4 */
4335 if(AOP_SIZE(left) == 4
4336 && AOP_SIZE(right) == 4) {
4337 genMultOneLong(left, right, result);
4341 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4344 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4345 /* should have been converted to function call */
4349 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4350 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4351 pic16_freeAsmop(result,NULL,ic,TRUE);
4354 /*-----------------------------------------------------------------*/
4355 /* genDivbits :- division of bits */
4356 /*-----------------------------------------------------------------*/
4357 static void genDivbits (operand *left,
4364 /* the result must be bit */
4365 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4366 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4370 pic16_emitcode("div","ab");
4371 pic16_emitcode("rrc","a");
4372 pic16_aopPut(AOP(result),"c",0);
4375 /*-----------------------------------------------------------------*/
4376 /* genDivOneByte : 8 bit division */
4377 /*-----------------------------------------------------------------*/
4378 static void genDivOneByte (operand *left,
4382 sym_link *opetype = operandType(result);
4387 /* result = divident / divisor
4388 * - divident may be a register or a literal,
4389 * - divisor may be a register or a literal,
4390 * so there are 3 cases (literal / literal is optimized
4391 * by the front-end) to handle.
4392 * In addition we must handle signed and unsigned, which
4393 * result in 6 final different cases -- VR */
4397 size = AOP_SIZE(result) - 1;
4399 /* signed or unsigned */
4400 if (SPEC_USIGN(opetype)) {
4401 pCodeOp *pct1, /* count */
4404 symbol *label1, *label2, *label3;;
4407 /* unsigned is easy */
4409 pct1 = pic16_popGetTempReg(1);
4410 pct2 = pic16_popGetTempReg(1);
4411 pct3 = pic16_popGetTempReg(1);
4413 label1 = newiTempLabel(NULL);
4414 label2 = newiTempLabel(NULL);
4415 label3 = newiTempLabel(NULL);
4417 /* the following algorithm is extracted from divuint.c */
4419 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4420 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4422 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4424 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4426 pic16_emitpLabel(label1->key);
4429 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4433 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4437 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4439 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4440 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4442 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4443 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4444 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4446 pic16_emitpLabel( label3->key );
4447 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4448 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4452 pic16_emitpLabel(label2->key);
4453 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4454 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4455 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4457 /* result is in wreg */
4458 if(AOP_TYPE(result) != AOP_ACC)
4459 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4461 pic16_popReleaseTempReg( pct3, 1);
4462 pic16_popReleaseTempReg( pct2, 1);
4463 pic16_popReleaseTempReg( pct1, 1);
4468 /* signed is a little bit more difficult */
4470 /* save the signs of the operands */
4471 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4473 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4474 pic16_emitcode("push","acc"); /* save it on the stack */
4476 /* now sign adjust for both left & right */
4477 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4479 lbl = newiTempLabel(NULL);
4480 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4481 pic16_emitcode("cpl","a");
4482 pic16_emitcode("inc","a");
4483 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4484 pic16_emitcode("mov","b,a");
4486 /* sign adjust left side */
4487 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4490 lbl = newiTempLabel(NULL);
4491 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4492 pic16_emitcode("cpl","a");
4493 pic16_emitcode("inc","a");
4494 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4496 /* now the division */
4497 pic16_emitcode("div","ab");
4498 /* we are interested in the lower order
4500 pic16_emitcode("mov","b,a");
4501 lbl = newiTempLabel(NULL);
4502 pic16_emitcode("pop","acc");
4503 /* if there was an over flow we don't
4504 adjust the sign of the result */
4505 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4506 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4508 pic16_emitcode("clr","a");
4509 pic16_emitcode("subb","a,b");
4510 pic16_emitcode("mov","b,a");
4511 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4513 /* now we are done */
4514 pic16_aopPut(AOP(result),"b",0);
4516 pic16_emitcode("mov","c,b.7");
4517 pic16_emitcode("subb","a,acc");
4520 pic16_aopPut(AOP(result),"a",offset++);
4524 /*-----------------------------------------------------------------*/
4525 /* genDiv - generates code for division */
4526 /*-----------------------------------------------------------------*/
4527 static void genDiv (iCode *ic)
4529 operand *left = IC_LEFT(ic);
4530 operand *right = IC_RIGHT(ic);
4531 operand *result= IC_RESULT(ic);
4534 /* Division is a very lengthy algorithm, so it is better
4535 * to call support routines than inlining algorithm.
4536 * Division functions written here just in case someone
4537 * wants to inline and not use the support libraries -- VR */
4541 /* assign the amsops */
4542 pic16_aopOp (left,ic,FALSE);
4543 pic16_aopOp (right,ic,FALSE);
4544 pic16_aopOp (result,ic,TRUE);
4546 /* special cases first */
4548 if (AOP_TYPE(left) == AOP_CRY &&
4549 AOP_TYPE(right)== AOP_CRY) {
4550 genDivbits(left,right,result);
4554 /* if both are of size == 1 */
4555 if (AOP_SIZE(left) == 1 &&
4556 AOP_SIZE(right) == 1 ) {
4557 genDivOneByte(left,right,result);
4561 /* should have been converted to function call */
4564 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4565 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4566 pic16_freeAsmop(result,NULL,ic,TRUE);
4569 /*-----------------------------------------------------------------*/
4570 /* genModbits :- modulus of bits */
4571 /*-----------------------------------------------------------------*/
4572 static void genModbits (operand *left,
4580 werror(W_POSSBUG2, __FILE__, __LINE__);
4581 /* the result must be bit */
4582 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4583 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4587 pic16_emitcode("div","ab");
4588 pic16_emitcode("mov","a,b");
4589 pic16_emitcode("rrc","a");
4590 pic16_aopPut(AOP(result),"c",0);
4593 /*-----------------------------------------------------------------*/
4594 /* genModOneByte : 8 bit modulus */
4595 /*-----------------------------------------------------------------*/
4596 static void genModOneByte (operand *left,
4600 sym_link *opetype = operandType(result);
4605 werror(W_POSSBUG2, __FILE__, __LINE__);
4607 /* signed or unsigned */
4608 if (SPEC_USIGN(opetype)) {
4609 /* unsigned is easy */
4610 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4611 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4613 pic16_emitcode("div","ab");
4614 pic16_aopPut(AOP(result),"b",0);
4618 /* signed is a little bit more difficult */
4620 /* save the signs of the operands */
4621 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4624 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4625 pic16_emitcode("push","acc"); /* save it on the stack */
4627 /* now sign adjust for both left & right */
4628 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4631 lbl = newiTempLabel(NULL);
4632 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4633 pic16_emitcode("cpl","a");
4634 pic16_emitcode("inc","a");
4635 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4636 pic16_emitcode("mov","b,a");
4638 /* sign adjust left side */
4639 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4642 lbl = newiTempLabel(NULL);
4643 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4644 pic16_emitcode("cpl","a");
4645 pic16_emitcode("inc","a");
4646 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4648 /* now the multiplication */
4649 pic16_emitcode("div","ab");
4650 /* we are interested in the lower order
4652 lbl = newiTempLabel(NULL);
4653 pic16_emitcode("pop","acc");
4654 /* if there was an over flow we don't
4655 adjust the sign of the result */
4656 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4657 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4659 pic16_emitcode("clr","a");
4660 pic16_emitcode("subb","a,b");
4661 pic16_emitcode("mov","b,a");
4662 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4664 /* now we are done */
4665 pic16_aopPut(AOP(result),"b",0);
4669 /*-----------------------------------------------------------------*/
4670 /* genMod - generates code for division */
4671 /*-----------------------------------------------------------------*/
4672 static void genMod (iCode *ic)
4674 operand *left = IC_LEFT(ic);
4675 operand *right = IC_RIGHT(ic);
4676 operand *result= IC_RESULT(ic);
4680 /* assign the amsops */
4681 pic16_aopOp (left,ic,FALSE);
4682 pic16_aopOp (right,ic,FALSE);
4683 pic16_aopOp (result,ic,TRUE);
4685 /* special cases first */
4687 if (AOP_TYPE(left) == AOP_CRY &&
4688 AOP_TYPE(right)== AOP_CRY) {
4689 genModbits(left,right,result);
4693 /* if both are of size == 1 */
4694 if (AOP_SIZE(left) == 1 &&
4695 AOP_SIZE(right) == 1 ) {
4696 genModOneByte(left,right,result);
4700 /* should have been converted to function call */
4704 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4705 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4706 pic16_freeAsmop(result,NULL,ic,TRUE);
4709 /*-----------------------------------------------------------------*/
4710 /* genIfxJump :- will create a jump depending on the ifx */
4711 /*-----------------------------------------------------------------*/
4713 note: May need to add parameter to indicate when a variable is in bit space.
4715 static void genIfxJump (iCode *ic, char *jval)
4719 /* if true label then we jump if condition
4721 if ( IC_TRUE(ic) ) {
4723 if(strcmp(jval,"a") == 0)
4725 else if (strcmp(jval,"c") == 0)
4728 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4729 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4732 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4733 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4737 /* false label is present */
4738 if(strcmp(jval,"a") == 0)
4740 else if (strcmp(jval,"c") == 0)
4743 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4744 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4747 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4748 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4753 /* mark the icode as generated */
4757 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4761 /* if true label then we jump if condition
4763 if ( IC_TRUE(ic) ) {
4764 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4765 pic16_emitpcode(POC_BTFSC, jop);
4767 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4768 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4771 /* false label is present */
4772 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4773 pic16_emitpcode(POC_BTFSS, jop);
4775 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4776 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4780 /* mark the icode as generated */
4787 /*-----------------------------------------------------------------*/
4789 /*-----------------------------------------------------------------*/
4790 static void genSkip(iCode *ifx,int status_bit)
4792 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4796 if ( IC_TRUE(ifx) ) {
4797 switch(status_bit) {
4812 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4813 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4817 switch(status_bit) {
4831 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4832 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4839 /*-----------------------------------------------------------------*/
4841 /*-----------------------------------------------------------------*/
4842 static void genSkipc(resolvedIfx *rifx)
4844 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4854 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4855 rifx->generated = 1;
4858 #if !(USE_SIMPLE_GENCMP)
4859 /*-----------------------------------------------------------------*/
4861 /*-----------------------------------------------------------------*/
4862 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4864 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4869 if( (rifx->condition ^ invert_condition) & 1)
4874 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4875 rifx->generated = 1;
4880 /*-----------------------------------------------------------------*/
4882 /*-----------------------------------------------------------------*/
4883 static void genSkipz(iCode *ifx, int condition)
4894 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4896 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4899 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4901 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4906 #if !(USE_SIMPLE_GENCMP)
4907 /*-----------------------------------------------------------------*/
4909 /*-----------------------------------------------------------------*/
4910 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4916 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4918 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4921 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4922 rifx->generated = 1;
4927 /*-----------------------------------------------------------------*/
4928 /* genChkZeroes :- greater or less than comparison */
4929 /* For each byte in a literal that is zero, inclusive or the */
4930 /* the corresponding byte in the operand with W */
4931 /* returns true if any of the bytes are zero */
4932 /*-----------------------------------------------------------------*/
4933 static int genChkZeroes(operand *op, int lit, int size)
4940 i = (lit >> (size*8)) & 0xff;
4944 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4946 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4956 /*-----------------------------------------------------------------*/
4957 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4958 /* aop (if it's NOT a literal) or from lit (if */
4959 /* aop is a literal) */
4960 /*-----------------------------------------------------------------*/
4961 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4962 if (aop->type == AOP_LIT) {
4963 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4965 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4969 /*-----------------------------------------------------------------*/
4970 /* genCmp :- greater or less than comparison */
4971 /*-----------------------------------------------------------------*/
4973 #if USE_SIMPLE_GENCMP /* { */
4975 /* genCmp performs a left < right comparison, stores
4976 * the outcome in result (if != NULL) and generates
4977 * control flow code for the ifx (if != NULL).
4979 * This version leaves in sequences like
4980 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4981 * which should be optmized by the peephole
4982 * optimizer - RN 2005-01-01 */
4983 static void genCmp (operand *left,operand *right,
4984 operand *result, iCode *ifx, int sign)
4997 assert (AOP_SIZE(left) == AOP_SIZE(right));
4998 assert (left && right);
5000 size = AOP_SIZE(right) - 1;
5001 mask = (0x100UL << (size*8)) - 1;
5002 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5007 resolveIfx (&rIfx, ifx);
5009 /* handle for special cases */
5010 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5013 /**********************************************************************
5014 * handle bits - bit compares are promoted to int compares seemingly! *
5015 **********************************************************************/
5017 // THIS IS COMPLETELY UNTESTED!
5018 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5019 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5020 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5021 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5024 // 1 < {0,1} is false --> clear C by skipping the next instruction
5025 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5026 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5027 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5028 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5029 emitCLRC; // only skipped for left=0 && right=1
5031 goto correct_result_in_carry;
5035 /*************************************************
5036 * make sure that left is register (or the like) *
5037 *************************************************/
5038 if (!isAOP_REGlike(left)) {
5039 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5040 assert (isAOP_LIT(left));
5041 assert (isAOP_REGlike(right));
5042 // swap left and right
5043 // left < right <==> right > left <==> (right >= left + 1)
5044 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5046 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5047 // MAXVALUE < right? always false
5048 if (performedLt) emitCLRC; else emitSETC;
5049 goto correct_result_in_carry;
5052 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5053 // that's why we handled it above.
5060 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5061 } else if (isAOP_LIT(right)) {
5062 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5065 assert (isAOP_REGlike(left)); // left must be register or the like
5066 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5068 /*************************************************
5069 * special cases go here *
5070 *************************************************/
5072 if (isAOP_LIT(right)) {
5074 // unsigned comparison to a literal
5075 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5077 // unsigned left < 0? always false
5078 if (performedLt) emitCLRC; else emitSETC;
5079 goto correct_result_in_carry;
5082 // signed comparison to a literal
5083 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5084 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5085 // signed left < 0x80000000? always false
5086 if (performedLt) emitCLRC; else emitSETC;
5087 goto correct_result_in_carry;
5088 } else if (lit == 0) {
5089 // compare left < 0; set CARRY if SIGNBIT(left) is set
5090 if (performedLt) emitSETC; else emitCLRC;
5091 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5092 if (performedLt) emitCLRC; else emitSETC;
5093 goto correct_result_in_carry;
5096 } // right is literal
5098 /*************************************************
5099 * perform a general case comparison *
5100 * make sure we get CARRY==1 <==> left >= right *
5101 *************************************************/
5102 // compare most significant bytes
5103 //DEBUGpc ("comparing bytes at offset %d", size);
5105 // unsigned comparison
5106 mov2w_regOrLit (AOP(right), lit, size);
5107 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5109 // signed comparison
5110 // (add 2^n to both operands then perform an unsigned comparison)
5111 if (isAOP_LIT(right)) {
5112 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5113 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5115 if (litbyte == 0x80) {
5116 // left >= 0x80 -- always true, but more bytes to come
5117 pic16_mov2w (AOP(left), size);
5118 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5121 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5122 pic16_mov2w (AOP(left), size);
5123 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5124 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5127 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5128 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5129 pic16_mov2w (AOP(left), size);
5130 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5131 pic16_emitpcode (POC_MOVWF, pctemp);
5132 pic16_mov2w (AOP(right), size);
5133 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5134 pic16_emitpcode (POC_SUBFW, pctemp);
5135 //pic16_popReleaseTempReg(pctemp, 1);
5139 // compare remaining bytes (treat as unsigned case from above)
5140 templbl = newiTempLabel ( NULL );
5143 //DEBUGpc ("comparing bytes at offset %d", offs);
5144 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5145 mov2w_regOrLit (AOP(right), lit, offs);
5146 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5148 pic16_emitpLabel (templbl->key);
5149 goto result_in_carry;
5153 /****************************************************
5154 * now CARRY contains the result of the comparison: *
5155 * SUBWF sets CARRY iff *
5156 * F-W >= 0 <==> F >= W <==> !(F < W) *
5157 * (F=left, W=right) *
5158 ****************************************************/
5161 if (result && AOP_TYPE(result) != AOP_CRY) {
5162 // value will be stored
5165 // value wil only be used in the following genSkipc()
5166 rIfx.condition ^= 1;
5170 correct_result_in_carry:
5172 // assign result to variable (if neccessary)
5173 if (result && AOP_TYPE(result) != AOP_CRY) {
5174 //DEBUGpc ("assign result");
5175 size = AOP_SIZE(result);
5177 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5179 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5182 // perform conditional jump
5184 //DEBUGpc ("generate control flow");
5193 static void genCmp (operand *left,operand *right,
5194 operand *result, iCode *ifx, int sign)
5196 int size; //, offset = 0 ;
5197 unsigned long lit = 0L,i = 0;
5198 resolvedIfx rFalseIfx;
5199 // resolvedIfx rTrueIfx;
5201 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5204 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5205 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5211 resolveIfx(&rFalseIfx,ifx);
5212 truelbl = newiTempLabel(NULL);
5213 size = max(AOP_SIZE(left),AOP_SIZE(right));
5215 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5219 /* if literal is on the right then swap with left */
5220 if ((AOP_TYPE(right) == AOP_LIT)) {
5221 operand *tmp = right ;
5222 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5223 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5226 lit = (lit - 1) & mask;
5229 rFalseIfx.condition ^= 1;
5232 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5233 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5237 //if(IC_TRUE(ifx) == NULL)
5238 /* if left & right are bit variables */
5239 if (AOP_TYPE(left) == AOP_CRY &&
5240 AOP_TYPE(right) == AOP_CRY ) {
5241 assert (0 && "bit variables used in genCmp");
5242 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5243 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5245 /* subtract right from left if at the
5246 end the carry flag is set then we know that
5247 left is greater than right */
5249 symbol *lbl = newiTempLabel(NULL);
5252 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5253 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5257 if(AOP_TYPE(right) == AOP_LIT) {
5259 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5261 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5268 genSkipCond(&rFalseIfx,left,size-1,7);
5270 /* no need to compare to 0...*/
5271 /* NOTE: this is a de-generate compare that most certainly
5272 * creates some dead code. */
5273 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5275 if(ifx) ifx->generated = 1;
5282 //i = (lit >> (size*8)) & 0xff;
5283 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5285 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5287 i = ((0-lit) & 0xff);
5290 /* lit is 0x7f, all signed chars are less than
5291 * this except for 0x7f itself */
5292 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5293 genSkipz2(&rFalseIfx,0);
5295 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5296 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5297 genSkipc(&rFalseIfx);
5302 genSkipz2(&rFalseIfx,1);
5304 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5305 genSkipc(&rFalseIfx);
5309 if(ifx) ifx->generated = 1;
5313 /* chars are out of the way. now do ints and longs */
5316 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5323 genSkipCond(&rFalseIfx,left,size,7);
5324 if(ifx) ifx->generated = 1;
5329 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5331 //rFalseIfx.condition ^= 1;
5332 //genSkipCond(&rFalseIfx,left,size,7);
5333 //rFalseIfx.condition ^= 1;
5335 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5336 if(rFalseIfx.condition)
5337 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5339 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5341 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5342 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5343 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5346 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5348 if(rFalseIfx.condition) {
5350 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5356 genSkipc(&rFalseIfx);
5357 pic16_emitpLabel(truelbl->key);
5358 if(ifx) ifx->generated = 1;
5365 if( (lit & 0xff) == 0) {
5366 /* lower byte is zero */
5367 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5368 i = ((lit >> 8) & 0xff) ^0x80;
5369 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5370 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5371 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5372 genSkipc(&rFalseIfx);
5375 if(ifx) ifx->generated = 1;
5380 /* Special cases for signed longs */
5381 if( (lit & 0xffffff) == 0) {
5382 /* lower byte is zero */
5383 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5384 i = ((lit >> 8*3) & 0xff) ^0x80;
5385 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5386 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5387 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5388 genSkipc(&rFalseIfx);
5391 if(ifx) ifx->generated = 1;
5399 if(lit & (0x80 << (size*8))) {
5400 /* lit is negative */
5401 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5403 //genSkipCond(&rFalseIfx,left,size,7);
5405 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5407 if(rFalseIfx.condition)
5408 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5410 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5414 /* lit is positive */
5415 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5416 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5417 if(rFalseIfx.condition)
5418 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5420 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5425 This works, but is only good for ints.
5426 It also requires a "known zero" register.
5427 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5428 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5429 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5430 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5431 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5432 genSkipc(&rFalseIfx);
5434 pic16_emitpLabel(truelbl->key);
5435 if(ifx) ifx->generated = 1;
5439 /* There are no more special cases, so perform a general compare */
5441 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5442 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5446 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5448 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5450 //rFalseIfx.condition ^= 1;
5451 genSkipc(&rFalseIfx);
5453 pic16_emitpLabel(truelbl->key);
5455 if(ifx) ifx->generated = 1;
5462 /* sign is out of the way. So now do an unsigned compare */
5463 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5466 /* General case - compare to an unsigned literal on the right.*/
5468 i = (lit >> (size*8)) & 0xff;
5469 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5470 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5472 i = (lit >> (size*8)) & 0xff;
5475 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5477 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5479 /* this byte of the lit is zero,
5480 *if it's not the last then OR in the variable */
5482 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5487 pic16_emitpLabel(lbl->key);
5488 // pic16_emitpLabel(truelbl->key);
5489 //if(emitFinalCheck)
5490 genSkipc(&rFalseIfx);
5492 pic16_emitpLabel(truelbl->key);
5494 if(ifx) ifx->generated = 1;
5501 if(AOP_TYPE(left) == AOP_LIT) {
5502 //symbol *lbl = newiTempLabel(NULL);
5504 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5507 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5510 if((lit == 0) && (sign == 0)){
5513 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5515 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5517 genSkipz2(&rFalseIfx,0);
5518 if(ifx) ifx->generated = 1;
5525 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5526 /* degenerate compare can never be true */
5527 if(rFalseIfx.condition == 0)
5528 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5530 if(ifx) ifx->generated = 1;
5535 /* signed comparisons to a literal byte */
5537 int lp1 = (lit+1) & 0xff;
5539 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5542 rFalseIfx.condition ^= 1;
5543 genSkipCond(&rFalseIfx,right,0,7);
5546 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5547 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5548 genSkipz2(&rFalseIfx,1);
5551 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5552 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5553 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5554 rFalseIfx.condition ^= 1;
5555 genSkipc(&rFalseIfx);
5559 /* unsigned comparisons to a literal byte */
5561 switch(lit & 0xff ) {
5563 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5564 genSkipz2(&rFalseIfx,0);
5567 rFalseIfx.condition ^= 1;
5568 genSkipCond(&rFalseIfx,right,0,7);
5572 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5573 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5574 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5575 rFalseIfx.condition ^= 1;
5576 if (AOP_TYPE(result) == AOP_CRY)
5577 genSkipc(&rFalseIfx);
5579 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5580 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5586 if(ifx) ifx->generated = 1;
5587 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5593 /* Size is greater than 1 */
5601 /* this means lit = 0xffffffff, or -1 */
5604 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5605 rFalseIfx.condition ^= 1;
5606 genSkipCond(&rFalseIfx,right,size,7);
5607 if(ifx) ifx->generated = 1;
5609 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5618 if(rFalseIfx.condition) {
5619 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5620 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5623 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5625 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5629 if(rFalseIfx.condition) {
5630 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5631 pic16_emitpLabel(truelbl->key);
5633 rFalseIfx.condition ^= 1;
5634 genSkipCond(&rFalseIfx,right,s,7);
5637 if(ifx) ifx->generated = 1;
5639 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5645 if((size == 1) && (0 == (lp1&0xff))) {
5646 /* lower byte of signed word is zero */
5647 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5648 i = ((lp1 >> 8) & 0xff) ^0x80;
5649 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5650 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5651 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5653 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5655 if(ifx) ifx->generated = 1;
5658 rFalseIfx.condition ^= 1;
5659 genSkipc(&rFalseIfx);
5660 if(ifx) ifx->generated = 1;
5666 if(lit & (0x80 << (size*8))) {
5667 /* Lit is less than zero */
5668 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5669 //rFalseIfx.condition ^= 1;
5670 //genSkipCond(&rFalseIfx,left,size,7);
5671 //rFalseIfx.condition ^= 1;
5672 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5673 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5675 if(rFalseIfx.condition)
5676 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5678 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5682 /* Lit is greater than or equal to zero */
5683 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5684 //rFalseIfx.condition ^= 1;
5685 //genSkipCond(&rFalseIfx,right,size,7);
5686 //rFalseIfx.condition ^= 1;
5688 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5689 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5691 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5692 if(rFalseIfx.condition)
5693 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5695 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5699 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5700 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5704 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5706 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5708 rFalseIfx.condition ^= 1;
5709 //rFalseIfx.condition = 1;
5710 genSkipc(&rFalseIfx);
5712 pic16_emitpLabel(truelbl->key);
5714 if(ifx) ifx->generated = 1;
5717 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5724 /* compare word or long to an unsigned literal on the right.*/
5729 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5732 break; /* handled above */
5735 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5737 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5738 genSkipz2(&rFalseIfx,0);
5742 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5744 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5747 if(rFalseIfx.condition)
5748 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5750 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5753 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5754 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5756 rFalseIfx.condition ^= 1;
5757 genSkipc(&rFalseIfx);
5760 pic16_emitpLabel(truelbl->key);
5762 if(ifx) ifx->generated = 1;
5764 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5772 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5773 i = (lit >> (size*8)) & 0xff;
5775 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5776 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5779 i = (lit >> (size*8)) & 0xff;
5782 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5784 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5786 /* this byte of the lit is zero,
5787 * if it's not the last then OR in the variable */
5789 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5794 pic16_emitpLabel(lbl->key);
5796 rFalseIfx.condition ^= 1;
5798 genSkipc(&rFalseIfx);
5802 pic16_emitpLabel(truelbl->key);
5803 if(ifx) ifx->generated = 1;
5805 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5811 /* Compare two variables */
5813 DEBUGpic16_emitcode(";sign","%d",sign);
5817 /* Sigh. thus sucks... */
5821 pctemp = pic16_popGetTempReg(1);
5822 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5823 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5824 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5825 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5826 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5827 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5828 pic16_popReleaseTempReg(pctemp, 1);
5830 /* Signed char comparison */
5831 /* Special thanks to Nikolai Golovchenko for this snippet */
5832 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5833 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5834 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5835 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5836 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5837 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5839 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5840 genSkipc(&rFalseIfx);
5842 if(ifx) ifx->generated = 1;
5844 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5852 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5853 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5857 /* The rest of the bytes of a multi-byte compare */
5861 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5864 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5865 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5870 pic16_emitpLabel(lbl->key);
5872 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5873 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5874 (AOP_TYPE(result) == AOP_REG)) {
5875 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5876 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5878 genSkipc(&rFalseIfx);
5880 //genSkipc(&rFalseIfx);
5881 if(ifx) ifx->generated = 1;
5884 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5892 if ((AOP_TYPE(result) != AOP_CRY)
5893 && AOP_SIZE(result)) {
5894 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5896 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5898 pic16_outBitC(result);
5900 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5901 /* if the result is used in the next
5902 ifx conditional branch then generate
5903 code a little differently */
5905 genIfxJump (ifx,"c");
5907 pic16_outBitC(result);
5908 /* leave the result in acc */
5913 #elif 0 /* VR version of genCmp() */ /* } else { */
5915 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5916 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5917 operand *result, int offset, int invert_op)
5921 /* check condition, > or < ?? */
5922 if(rIfx->condition != 0)invert_op ^= 1;
5924 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5926 if(!ifx)invert_op ^= 1;
5928 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5929 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5932 if(!invert_op)return POC_CPFSGT;
5933 else return POC_CPFSLT;
5936 static int compareAopfirstpass=1;
5938 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5939 operand *oper, int offset, operand *result,
5940 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5946 /* invert if there is a result to be loaded, in order to fit,
5947 * SETC/CLRC sequence */
5948 if(AOP_SIZE(result))invert_op ^= 1;
5950 // if(sign && !offset)invert_op ^= 1;
5952 // if(sign)invert_op ^= 1;
5954 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5956 if(AOP_SIZE(result) && compareAopfirstpass) {
5959 pic16_emitpcode(POC_SETF, pcop2);
5964 pic16_emitpcode(POC_CLRF, pcop2);
5970 compareAopfirstpass = 0;
5972 /* there is a bug when comparing operands with size > 1,
5973 * because higher bytes can be equal and test should be performed
5974 * to the next lower byte, current algorithm, considers operands
5975 * inequal in these cases! -- VR 20041107 */
5979 pic16_emitpcode(op, pcop);
5981 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5984 if((!sign || !offset) && AOP_SIZE(result)) {
5987 pic16_emitpcode(POC_CLRF, pcop2);
5992 pic16_emitpcode(POC_SETF, pcop2);
5997 /* don't emit final branch (offset == 0) */
6001 pic16_emitpcode(POC_RRCF, pcop2);
6003 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6006 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6007 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6008 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6010 truelbl = newiTempLabel( NULL );
6011 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6012 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6013 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6015 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6016 pic16_emitpLabel(truelbl->key);
6018 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6023 static void genCmp (operand *left, operand *right,
6024 operand *result, iCode *ifx, int sign)
6028 resolvedIfx rFalseIfx;
6029 symbol *falselbl, *tlbl;
6033 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6035 resolveIfx(&rFalseIfx, ifx);
6036 size = max(AOP_SIZE(left), AOP_SIZE(right));
6038 /* if left & right are bit variables */
6039 if(AOP_TYPE(left) == AOP_CRY
6040 && AOP_TYPE(right) == AOP_CRY ) {
6042 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6043 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6045 werror(W_POSSBUG2, __FILE__, __LINE__);
6049 /* if literal is on the right then swap with left */
6050 if((AOP_TYPE(right) == AOP_LIT)) {
6051 operand *tmp = right ;
6052 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6054 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6056 // lit = (lit - 1) & mask;
6059 rFalseIfx.condition ^= 1; /* reverse compare */
6061 if ((AOP_TYPE(left) == AOP_LIT)) {
6062 /* float compares are handled by support functions */
6063 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6066 /* actual comparing algorithm */
6067 // size = AOP_SIZE( right );
6069 falselbl = newiTempLabel( NULL );
6070 if(AOP_TYPE(left) == AOP_LIT) {
6071 /* compare to literal */
6072 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6075 pCodeOp *pct, *pct2;
6078 /* signed compare */
6079 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6081 pct = pic16_popCopyReg(&pic16_pc_prodl);
6082 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6083 tlbl = newiTempLabel( NULL );
6085 /* first compare signs:
6086 * a. if both are positive, compare just like unsigned
6087 * b. if both are negative, invert cmpop, compare just like unsigned
6088 * c. if different signs, determine the result directly */
6094 tlbl1 = newiTempLabel( NULL );
6095 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6099 /* literal is zero or positive:
6100 * a. if carry is zero, too, continue compare,
6101 * b. if carry is set, then continue depending on cmpop ^ condition:
6102 * 1. '<' return false (literal < variable),
6103 * 2. '>' return true (literal > variable) */
6104 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6105 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6108 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6109 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6113 /* literal is negative:
6114 * a. if carry is set, too, continue compare,
6115 * b. if carry is zero, then continue depending on cmpop ^ condition:
6116 * 1. '<' return true (literal < variable),
6117 * 2. '>' return false (literal > variable) */
6118 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6119 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6121 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6122 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6127 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6129 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6130 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6135 pic16_emitpLabel( tlbl1->key );
6138 compareAopfirstpass=1;
6139 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6140 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6141 // pic16_emitpcode(POC_MOVWF, pct);
6143 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6144 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6145 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6146 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6150 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6151 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6152 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6153 // pic16_emitpcode(POC_MOVWF, pct);
6155 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6156 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6157 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6158 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6159 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6162 if(ifx)ifx->generated = 1;
6164 if(AOP_SIZE(result)) {
6165 pic16_emitpLabel(tlbl->key);
6166 pic16_emitpLabel(falselbl->key);
6167 pic16_outBitOp( result, pct2 );
6169 pic16_emitpLabel(tlbl->key);
6173 /* unsigned compare */
6174 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6176 compareAopfirstpass=1;
6179 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6180 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6183 if(ifx)ifx->generated = 1;
6185 if(AOP_SIZE(result)) {
6186 pic16_emitpLabel(falselbl->key);
6187 pic16_outBitC( result );
6192 /* compare registers */
6193 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6197 pCodeOp *pct, *pct2;
6199 /* signed compare */
6200 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6202 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6203 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6204 tlbl = newiTempLabel( NULL );
6206 compareAopfirstpass=1;
6209 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6210 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6211 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6212 pic16_emitpcode(POC_MOVWF, pct);
6214 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6215 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6216 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6218 /* WREG already holds left + 0x80 */
6219 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6222 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6223 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6224 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6225 pic16_emitpcode(POC_MOVWF, pct);
6227 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6228 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6229 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6231 /* WREG already holds left + 0x80 */
6232 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6233 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6236 if(ifx)ifx->generated = 1;
6238 if(AOP_SIZE(result)) {
6239 pic16_emitpLabel(tlbl->key);
6240 pic16_emitpLabel(falselbl->key);
6241 pic16_outBitOp( result, pct2 );
6243 pic16_emitpLabel(tlbl->key);
6247 /* unsigned compare */
6248 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6250 compareAopfirstpass=1;
6253 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6254 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6258 if(ifx)ifx->generated = 1;
6259 if(AOP_SIZE(result)) {
6261 pic16_emitpLabel(falselbl->key);
6262 pic16_outBitC( result );
6273 /*-----------------------------------------------------------------*/
6274 /* genCmpGt :- greater than comparison */
6275 /*-----------------------------------------------------------------*/
6276 static void genCmpGt (iCode *ic, iCode *ifx)
6278 operand *left, *right, *result;
6279 sym_link *letype , *retype;
6285 right= IC_RIGHT(ic);
6286 result = IC_RESULT(ic);
6288 letype = getSpec(operandType(left));
6289 retype =getSpec(operandType(right));
6290 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6291 /* assign the amsops */
6292 pic16_aopOp (left,ic,FALSE);
6293 pic16_aopOp (right,ic,FALSE);
6294 pic16_aopOp (result,ic,TRUE);
6296 genCmp(right, left, result, ifx, sign);
6298 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6299 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6300 pic16_freeAsmop(result,NULL,ic,TRUE);
6303 /*-----------------------------------------------------------------*/
6304 /* genCmpLt - less than comparisons */
6305 /*-----------------------------------------------------------------*/
6306 static void genCmpLt (iCode *ic, iCode *ifx)
6308 operand *left, *right, *result;
6309 sym_link *letype , *retype;
6315 right= IC_RIGHT(ic);
6316 result = IC_RESULT(ic);
6318 letype = getSpec(operandType(left));
6319 retype =getSpec(operandType(right));
6320 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6322 /* assign the amsops */
6323 pic16_aopOp (left,ic,FALSE);
6324 pic16_aopOp (right,ic,FALSE);
6325 pic16_aopOp (result,ic,TRUE);
6327 genCmp(left, right, result, ifx, sign);
6329 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6330 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6331 pic16_freeAsmop(result,NULL,ic,TRUE);
6336 // FIXME reenable literal optimisation when the pic16 port is stable
6338 /*-----------------------------------------------------------------*/
6339 /* genc16bit2lit - compare a 16 bit value to a literal */
6340 /*-----------------------------------------------------------------*/
6341 static void genc16bit2lit(operand *op, int lit, int offset)
6345 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6346 if( (lit&0xff) == 0)
6351 switch( BYTEofLONG(lit,i)) {
6353 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6356 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6359 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6362 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6363 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6368 switch( BYTEofLONG(lit,i)) {
6370 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6374 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6378 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6381 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6383 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6392 /*-----------------------------------------------------------------*/
6393 /* gencjneshort - compare and jump if not equal */
6394 /*-----------------------------------------------------------------*/
6395 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6397 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6399 int res_offset = 0; /* the result may be a different size then left or right */
6400 int res_size = AOP_SIZE(result);
6402 symbol *lbl, *lbl_done;
6404 unsigned long lit = 0L;
6405 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6407 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6408 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6410 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6411 resolveIfx(&rIfx,ifx);
6412 lbl = newiTempLabel(NULL);
6413 lbl_done = newiTempLabel(NULL);
6416 /* if the left side is a literal or
6417 if the right is in a pointer register and left
6419 if ((AOP_TYPE(left) == AOP_LIT) ||
6420 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6425 if(AOP_TYPE(right) == AOP_LIT)
6426 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6428 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6429 preserve_result = 1;
6431 if(result && !preserve_result)
6434 for(i = 0; i < AOP_SIZE(result); i++)
6435 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6439 /* if the right side is a literal then anything goes */
6440 if (AOP_TYPE(right) == AOP_LIT &&
6441 AOP_TYPE(left) != AOP_DIR ) {
6444 genc16bit2lit(left, lit, 0);
6446 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6449 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6452 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6453 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6455 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6459 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6461 if(res_offset < res_size-1)
6469 /* if the right side is in a register or in direct space or
6470 if the left is a pointer register & right is not */
6471 else if (AOP_TYPE(right) == AOP_REG ||
6472 AOP_TYPE(right) == AOP_DIR ||
6473 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6474 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6475 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6476 int lbl_key = lbl->key;
6479 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6480 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6482 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6483 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6484 __FUNCTION__,__LINE__);
6488 /* switch(size) { */
6490 /* genc16bit2lit(left, lit, 0); */
6492 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6497 if((AOP_TYPE(left) == AOP_DIR) &&
6498 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6500 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6501 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6503 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6505 switch (lit & 0xff) {
6507 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6510 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6511 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6512 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6516 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6517 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6518 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6519 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6523 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6524 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6529 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6532 if(AOP_TYPE(result) == AOP_CRY) {
6533 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6538 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6540 /* fix me. probably need to check result size too */
6541 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6546 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6547 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6554 if(res_offset < res_size-1)
6559 } else if(AOP_TYPE(right) == AOP_REG &&
6560 AOP_TYPE(left) != AOP_DIR){
6563 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6564 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6565 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6570 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6572 if(res_offset < res_size-1)
6577 /* right is a pointer reg need both a & b */
6579 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6581 pic16_emitcode("mov","b,%s",l);
6582 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6583 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6588 if(result && preserve_result)
6591 for(i = 0; i < AOP_SIZE(result); i++)
6592 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6595 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6597 if(result && preserve_result)
6598 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6601 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6603 pic16_emitpLabel(lbl->key);
6605 if(result && preserve_result)
6608 for(i = 0; i < AOP_SIZE(result); i++)
6609 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6611 pic16_emitpLabel(lbl_done->key);
6614 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6622 /*-----------------------------------------------------------------*/
6623 /* gencjne - compare and jump if not equal */
6624 /*-----------------------------------------------------------------*/
6625 static void gencjne(operand *left, operand *right, iCode *ifx)
6627 symbol *tlbl = newiTempLabel(NULL);
6629 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6630 gencjneshort(left, right, lbl);
6632 pic16_emitcode("mov","a,%s",one);
6633 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6634 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6635 pic16_emitcode("clr","a");
6636 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6638 pic16_emitpLabel(lbl->key);
6639 pic16_emitpLabel(tlbl->key);
6645 /*-----------------------------------------------------------------*/
6646 /* is_LitOp - check if operand has to be treated as literal */
6647 /*-----------------------------------------------------------------*/
6648 static bool is_LitOp(operand *op)
6650 return ((AOP_TYPE(op) == AOP_LIT)
6651 || ( (AOP_TYPE(op) == AOP_PCODE)
6652 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6653 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6656 /*-----------------------------------------------------------------*/
6657 /* is_LitAOp - check if operand has to be treated as literal */
6658 /*-----------------------------------------------------------------*/
6659 static bool is_LitAOp(asmop *aop)
6661 return ((aop->type == AOP_LIT)
6662 || ( (aop->type == AOP_PCODE)
6663 && ( (aop->aopu.pcop->type == PO_LITERAL)
6664 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6669 /*-----------------------------------------------------------------*/
6670 /* genCmpEq - generates code for equal to */
6671 /*-----------------------------------------------------------------*/
6672 static void genCmpEq (iCode *ic, iCode *ifx)
6674 operand *left, *right, *result;
6675 symbol *falselbl = newiTempLabel(NULL);
6676 symbol *donelbl = newiTempLabel(NULL);
6678 int preserve_result = 0;
6679 int generate_result = 0;
6681 unsigned long lit = -1;
6685 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6686 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6687 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6689 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6691 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6693 werror(W_POSSBUG2, __FILE__, __LINE__);
6694 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6695 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6699 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6701 operand *tmp = right ;
6706 if (AOP_TYPE(right) == AOP_LIT) {
6707 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6710 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6711 preserve_result = 1;
6713 if(result && AOP_SIZE(result))
6714 generate_result = 1;
6716 if(generate_result && !preserve_result)
6718 for(i = 0; i < AOP_SIZE(result); i++)
6719 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6722 for(i=0; i < AOP_SIZE(left); i++)
6724 if(AOP_TYPE(left) != AOP_ACC)
6727 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6729 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6731 if(is_LitOp(right)) {
6732 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6733 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6736 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6738 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6743 if(generate_result && preserve_result)
6745 for(i = 0; i < AOP_SIZE(result); i++)
6746 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6750 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6752 if(generate_result && preserve_result)
6753 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6755 if(ifx && IC_TRUE(ifx))
6756 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6758 if(ifx && IC_FALSE(ifx))
6759 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6761 pic16_emitpLabel(falselbl->key);
6765 if(ifx && IC_FALSE(ifx))
6766 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6768 if(generate_result && preserve_result)
6770 for(i = 0; i < AOP_SIZE(result); i++)
6771 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6774 pic16_emitpLabel(donelbl->key);
6780 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6781 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6782 pic16_freeAsmop(result,NULL,ic,TRUE);
6788 // old version kept for reference
6790 /*-----------------------------------------------------------------*/
6791 /* genCmpEq - generates code for equal to */
6792 /*-----------------------------------------------------------------*/
6793 static void genCmpEq (iCode *ic, iCode *ifx)
6795 operand *left, *right, *result;
6796 unsigned long lit = 0L;
6798 symbol *falselbl = newiTempLabel(NULL);
6801 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6804 DEBUGpic16_emitcode ("; ifx is non-null","");
6806 DEBUGpic16_emitcode ("; ifx is null","");
6808 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6809 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6810 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6812 size = max(AOP_SIZE(left),AOP_SIZE(right));
6814 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6816 /* if literal, literal on the right or
6817 if the right is in a pointer register and left
6819 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6820 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6821 operand *tmp = right ;
6827 if(ifx && !AOP_SIZE(result)){
6829 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6830 /* if they are both bit variables */
6831 if (AOP_TYPE(left) == AOP_CRY &&
6832 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6833 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6834 if(AOP_TYPE(right) == AOP_LIT){
6835 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6837 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6838 pic16_emitcode("cpl","c");
6839 } else if(lit == 1L) {
6840 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6842 pic16_emitcode("clr","c");
6844 /* AOP_TYPE(right) == AOP_CRY */
6846 symbol *lbl = newiTempLabel(NULL);
6847 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6848 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6849 pic16_emitcode("cpl","c");
6850 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6852 /* if true label then we jump if condition
6854 tlbl = newiTempLabel(NULL);
6855 if ( IC_TRUE(ifx) ) {
6856 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6857 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6859 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6860 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6862 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6865 /* left and right are both bit variables, result is carry */
6868 resolveIfx(&rIfx,ifx);
6870 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6871 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6872 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6873 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6878 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6880 /* They're not both bit variables. Is the right a literal? */
6881 if(AOP_TYPE(right) == AOP_LIT) {
6882 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6887 switch(lit & 0xff) {
6889 if ( IC_TRUE(ifx) ) {
6890 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6892 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6894 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6895 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6899 if ( IC_TRUE(ifx) ) {
6900 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6902 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6904 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6905 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6909 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6911 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6916 /* end of size == 1 */
6920 genc16bit2lit(left,lit,offset);
6923 /* end of size == 2 */
6928 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6929 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6930 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6931 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6934 /* search for patterns that can be optimized */
6936 genc16bit2lit(left,lit,0);
6940 emitSKPZ; // if hi word unequal
6942 emitSKPNZ; // if hi word equal
6944 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6945 genc16bit2lit(left,lit,2);
6948 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6949 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6953 pic16_emitpLabel(falselbl->key);
6962 } else if(AOP_TYPE(right) == AOP_CRY ) {
6963 /* we know the left is not a bit, but that the right is */
6964 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6965 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6966 pic16_popGet(AOP(right),offset));
6967 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6969 /* if the two are equal, then W will be 0 and the Z bit is set
6970 * we could test Z now, or go ahead and check the high order bytes if
6971 * the variable we're comparing is larger than a byte. */
6974 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6976 if ( IC_TRUE(ifx) ) {
6978 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6979 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6982 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6983 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6987 /* They're both variables that are larger than bits */
6990 tlbl = newiTempLabel(NULL);
6993 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6994 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6996 if ( IC_TRUE(ifx) ) {
7000 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7002 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7003 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7007 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7010 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7011 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7016 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7018 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7019 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7023 if(s>1 && IC_TRUE(ifx)) {
7024 pic16_emitpLabel(tlbl->key);
7025 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7029 /* mark the icode as generated */
7034 /* if they are both bit variables */
7035 if (AOP_TYPE(left) == AOP_CRY &&
7036 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7037 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7038 if(AOP_TYPE(right) == AOP_LIT){
7039 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7041 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7042 pic16_emitcode("cpl","c");
7043 } else if(lit == 1L) {
7044 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7046 pic16_emitcode("clr","c");
7048 /* AOP_TYPE(right) == AOP_CRY */
7050 symbol *lbl = newiTempLabel(NULL);
7051 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7052 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7053 pic16_emitcode("cpl","c");
7054 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7057 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7058 pic16_outBitC(result);
7062 genIfxJump (ifx,"c");
7065 /* if the result is used in an arithmetic operation
7066 then put the result in place */
7067 pic16_outBitC(result);
7070 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7071 gencjne(left,right,result,ifx);
7074 gencjne(left,right,newiTempLabel(NULL));
7076 if(IC_TRUE(ifx)->key)
7077 gencjne(left,right,IC_TRUE(ifx)->key);
7079 gencjne(left,right,IC_FALSE(ifx)->key);
7083 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7084 pic16_aopPut(AOP(result),"a",0);
7089 genIfxJump (ifx,"a");
7093 /* if the result is used in an arithmetic operation
7094 then put the result in place */
7096 if (AOP_TYPE(result) != AOP_CRY)
7097 pic16_outAcc(result);
7099 /* leave the result in acc */
7103 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7104 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7105 pic16_freeAsmop(result,NULL,ic,TRUE);
7109 /*-----------------------------------------------------------------*/
7110 /* ifxForOp - returns the icode containing the ifx for operand */
7111 /*-----------------------------------------------------------------*/
7112 static iCode *ifxForOp ( operand *op, iCode *ic )
7116 /* if true symbol then needs to be assigned */
7117 if (IS_TRUE_SYMOP(op))
7120 /* if this has register type condition and
7121 the next instruction is ifx with the same operand
7122 and live to of the operand is upto the ifx only then */
7124 && ic->next->op == IFX
7125 && IC_COND(ic->next)->key == op->key
7126 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7128 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7134 ic->next->op == IFX &&
7135 IC_COND(ic->next)->key == op->key) {
7136 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7141 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7143 ic->next->op == IFX)
7144 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7147 ic->next->op == IFX &&
7148 IC_COND(ic->next)->key == op->key) {
7149 DEBUGpic16_emitcode ("; "," key is okay");
7150 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7151 OP_SYMBOL(op)->liveTo,
7156 /* the code below is completely untested
7157 * it just allows ulong2fs.c compile -- VR */
7160 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7161 __FILE__, __FUNCTION__, __LINE__);
7163 /* if this has register type condition and
7164 the next instruction is ifx with the same operand
7165 and live to of the operand is upto the ifx only then */
7167 ic->next->op == IFX &&
7168 IC_COND(ic->next)->key == op->key &&
7169 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7173 ic->next->op == IFX &&
7174 IC_COND(ic->next)->key == op->key) {
7175 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7179 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7180 __FILE__, __FUNCTION__, __LINE__);
7182 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7187 /*-----------------------------------------------------------------*/
7188 /* genAndOp - for && operation */
7189 /*-----------------------------------------------------------------*/
7190 static void genAndOp (iCode *ic)
7192 operand *left,*right, *result;
7197 /* note here that && operations that are in an
7198 if statement are taken away by backPatchLabels
7199 only those used in arthmetic operations remain */
7200 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7201 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7202 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7204 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7206 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7207 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7208 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7210 /* if both are bit variables */
7211 /* if (AOP_TYPE(left) == AOP_CRY && */
7212 /* AOP_TYPE(right) == AOP_CRY ) { */
7213 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7214 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7215 /* pic16_outBitC(result); */
7217 /* tlbl = newiTempLabel(NULL); */
7218 /* pic16_toBoolean(left); */
7219 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7220 /* pic16_toBoolean(right); */
7221 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7222 /* pic16_outBitAcc(result); */
7225 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7226 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7227 pic16_freeAsmop(result,NULL,ic,TRUE);
7231 /*-----------------------------------------------------------------*/
7232 /* genOrOp - for || operation */
7233 /*-----------------------------------------------------------------*/
7236 modified this code, but it doesn't appear to ever get called
7239 static void genOrOp (iCode *ic)
7241 operand *left,*right, *result;
7246 /* note here that || operations that are in an
7247 if statement are taken away by backPatchLabels
7248 only those used in arthmetic operations remain */
7249 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7250 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7251 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7253 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7255 /* if both are bit variables */
7256 if (AOP_TYPE(left) == AOP_CRY &&
7257 AOP_TYPE(right) == AOP_CRY ) {
7258 pic16_emitcode("clrc","");
7259 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7260 AOP(left)->aopu.aop_dir,
7261 AOP(left)->aopu.aop_dir);
7262 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7263 AOP(right)->aopu.aop_dir,
7264 AOP(right)->aopu.aop_dir);
7265 pic16_emitcode("setc","");
7268 tlbl = newiTempLabel(NULL);
7269 pic16_toBoolean(left);
7271 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7272 pic16_toBoolean(right);
7273 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7275 pic16_outBitAcc(result);
7278 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7279 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7280 pic16_freeAsmop(result,NULL,ic,TRUE);
7283 /*-----------------------------------------------------------------*/
7284 /* isLiteralBit - test if lit == 2^n */
7285 /*-----------------------------------------------------------------*/
7286 static int isLiteralBit(unsigned long lit)
7288 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7289 0x100L,0x200L,0x400L,0x800L,
7290 0x1000L,0x2000L,0x4000L,0x8000L,
7291 0x10000L,0x20000L,0x40000L,0x80000L,
7292 0x100000L,0x200000L,0x400000L,0x800000L,
7293 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7294 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7297 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7298 for(idx = 0; idx < 32; idx++)
7304 /*-----------------------------------------------------------------*/
7305 /* continueIfTrue - */
7306 /*-----------------------------------------------------------------*/
7307 static void continueIfTrue (iCode *ic)
7311 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7315 /*-----------------------------------------------------------------*/
7317 /*-----------------------------------------------------------------*/
7318 static void jumpIfTrue (iCode *ic)
7322 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7326 /*-----------------------------------------------------------------*/
7327 /* jmpTrueOrFalse - */
7328 /*-----------------------------------------------------------------*/
7329 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7331 // ugly but optimized by peephole
7334 symbol *nlbl = newiTempLabel(NULL);
7335 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7336 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7337 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7338 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7340 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7341 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7346 /*-----------------------------------------------------------------*/
7347 /* genAnd - code for and */
7348 /*-----------------------------------------------------------------*/
7349 static void genAnd (iCode *ic, iCode *ifx)
7351 operand *left, *right, *result;
7353 unsigned long lit = 0L;
7359 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7360 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7361 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7363 resolveIfx(&rIfx,ifx);
7365 /* if left is a literal & right is not then exchange them */
7366 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7367 AOP_NEEDSACC(left)) {
7368 operand *tmp = right ;
7373 /* if result = right then exchange them */
7374 if(pic16_sameRegs(AOP(result),AOP(right))){
7375 operand *tmp = right ;
7380 /* if right is bit then exchange them */
7381 if (AOP_TYPE(right) == AOP_CRY &&
7382 AOP_TYPE(left) != AOP_CRY){
7383 operand *tmp = right ;
7387 if(AOP_TYPE(right) == AOP_LIT)
7388 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7390 size = AOP_SIZE(result);
7392 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7395 // result = bit & yy;
7396 if (AOP_TYPE(left) == AOP_CRY){
7397 // c = bit & literal;
7398 if(AOP_TYPE(right) == AOP_LIT){
7400 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7403 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7406 if(size && (AOP_TYPE(result) == AOP_CRY)){
7407 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7410 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7414 pic16_emitcode("clr","c");
7417 if (AOP_TYPE(right) == AOP_CRY){
7419 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7420 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7423 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7425 pic16_emitcode("rrc","a");
7426 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7432 pic16_outBitC(result);
7434 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7435 genIfxJump(ifx, "c");
7439 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7440 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7441 if((AOP_TYPE(right) == AOP_LIT) &&
7442 (AOP_TYPE(result) == AOP_CRY) &&
7443 (AOP_TYPE(left) != AOP_CRY)){
7444 int posbit = isLiteralBit(lit);
7448 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7451 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7457 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7458 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7460 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7461 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7464 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7465 size = AOP_SIZE(left);
7468 int bp = posbit, ofs=0;
7475 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7476 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7480 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7481 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7483 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7490 symbol *tlbl = newiTempLabel(NULL);
7491 int sizel = AOP_SIZE(left);
7497 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7499 /* patch provided by Aaron Colwell */
7500 if((posbit = isLiteralBit(bytelit)) != 0) {
7501 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7502 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7503 (posbit-1),0, PO_GPR_REGISTER));
7505 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7506 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7508 if (bytelit == 0xff) {
7509 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7510 * a peephole could optimize it out -- VR */
7511 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7513 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7514 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7517 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7518 pic16_popGetLabel(tlbl->key));
7522 /* old code, left here for reference -- VR 09/2004 */
7523 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7525 if((posbit = isLiteralBit(bytelit)) != 0)
7526 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7528 if(bytelit != 0x0FFL)
7529 pic16_emitcode("anl","a,%s",
7530 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7531 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7537 // bit = left & literal
7540 pic16_emitpLabel(tlbl->key);
7542 // if(left & literal)
7545 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7548 pic16_emitpLabel(tlbl->key);
7553 pic16_outBitC(result);
7557 /* if left is same as result */
7558 if(pic16_sameRegs(AOP(result),AOP(left))){
7560 for(;size--; offset++,lit>>=8) {
7561 if(AOP_TYPE(right) == AOP_LIT){
7562 switch(lit & 0xff) {
7564 /* and'ing with 0 has clears the result */
7565 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7566 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7569 /* and'ing with 0xff is a nop when the result and left are the same */
7574 int p = pic16_my_powof2( (~lit) & 0xff );
7576 /* only one bit is set in the literal, so use a bcf instruction */
7577 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7578 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7581 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7582 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7583 if(know_W != (lit&0xff))
7584 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7586 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7591 if (AOP_TYPE(left) == AOP_ACC) {
7592 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7594 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7595 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7602 // left & result in different registers
7603 if(AOP_TYPE(result) == AOP_CRY){
7605 // if(size), result in bit
7606 // if(!size && ifx), conditional oper: if(left & right)
7607 symbol *tlbl = newiTempLabel(NULL);
7608 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7610 pic16_emitcode("setb","c");
7612 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7613 pic16_emitcode("anl","a,%s",
7614 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7615 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7620 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7621 pic16_outBitC(result);
7623 jmpTrueOrFalse(ifx, tlbl);
7625 for(;(size--);offset++) {
7627 // result = left & right
7628 if(AOP_TYPE(right) == AOP_LIT){
7629 int t = (lit >> (offset*8)) & 0x0FFL;
7632 pic16_emitcode("clrf","%s",
7633 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7634 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7637 pic16_emitcode("movf","%s,w",
7638 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7639 pic16_emitcode("movwf","%s",
7640 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7641 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7642 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7645 pic16_emitcode("movlw","0x%x",t);
7646 pic16_emitcode("andwf","%s,w",
7647 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7648 pic16_emitcode("movwf","%s",
7649 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7651 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7652 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7653 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7658 if (AOP_TYPE(left) == AOP_ACC) {
7659 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7660 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7662 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7663 pic16_emitcode("andwf","%s,w",
7664 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7665 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7666 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7668 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7669 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7675 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7676 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7677 pic16_freeAsmop(result,NULL,ic,TRUE);
7680 /*-----------------------------------------------------------------*/
7681 /* genOr - code for or */
7682 /*-----------------------------------------------------------------*/
7683 static void genOr (iCode *ic, iCode *ifx)
7685 operand *left, *right, *result;
7687 unsigned long lit = 0L;
7689 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7691 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7692 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7693 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7695 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7697 /* if left is a literal & right is not then exchange them */
7698 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7699 AOP_NEEDSACC(left)) {
7700 operand *tmp = right ;
7705 /* if result = right then exchange them */
7706 if(pic16_sameRegs(AOP(result),AOP(right))){
7707 operand *tmp = right ;
7712 /* if right is bit then exchange them */
7713 if (AOP_TYPE(right) == AOP_CRY &&
7714 AOP_TYPE(left) != AOP_CRY){
7715 operand *tmp = right ;
7720 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7722 if(AOP_TYPE(right) == AOP_LIT)
7723 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7725 size = AOP_SIZE(result);
7729 if (AOP_TYPE(left) == AOP_CRY){
7730 if(AOP_TYPE(right) == AOP_LIT){
7731 // c = bit & literal;
7733 // lit != 0 => result = 1
7734 if(AOP_TYPE(result) == AOP_CRY){
7736 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7737 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7738 // AOP(result)->aopu.aop_dir,
7739 // AOP(result)->aopu.aop_dir);
7741 continueIfTrue(ifx);
7745 // lit == 0 => result = left
7746 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7748 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7751 if (AOP_TYPE(right) == AOP_CRY){
7752 if(pic16_sameRegs(AOP(result),AOP(left))){
7754 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7755 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7756 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7758 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7759 AOP(result)->aopu.aop_dir,
7760 AOP(result)->aopu.aop_dir);
7761 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7762 AOP(right)->aopu.aop_dir,
7763 AOP(right)->aopu.aop_dir);
7764 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7765 AOP(result)->aopu.aop_dir,
7766 AOP(result)->aopu.aop_dir);
7768 if( AOP_TYPE(result) == AOP_ACC) {
7769 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7770 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7771 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7772 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7776 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7777 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7778 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7779 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7781 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7782 AOP(result)->aopu.aop_dir,
7783 AOP(result)->aopu.aop_dir);
7784 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7785 AOP(right)->aopu.aop_dir,
7786 AOP(right)->aopu.aop_dir);
7787 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7788 AOP(left)->aopu.aop_dir,
7789 AOP(left)->aopu.aop_dir);
7790 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7791 AOP(result)->aopu.aop_dir,
7792 AOP(result)->aopu.aop_dir);
7797 symbol *tlbl = newiTempLabel(NULL);
7798 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7801 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7802 if( AOP_TYPE(right) == AOP_ACC) {
7803 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7805 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7806 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7811 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7812 pic16_emitcode(";XXX setb","c");
7813 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7814 AOP(left)->aopu.aop_dir,tlbl->key+100);
7815 pic16_toBoolean(right);
7816 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7817 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7818 jmpTrueOrFalse(ifx, tlbl);
7822 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7829 pic16_outBitC(result);
7831 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7832 genIfxJump(ifx, "c");
7836 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7837 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7838 if((AOP_TYPE(right) == AOP_LIT) &&
7839 (AOP_TYPE(result) == AOP_CRY) &&
7840 (AOP_TYPE(left) != AOP_CRY)){
7842 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7845 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7847 continueIfTrue(ifx);
7850 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7851 // lit = 0, result = boolean(left)
7853 pic16_emitcode(";XXX setb","c");
7854 pic16_toBoolean(right);
7856 symbol *tlbl = newiTempLabel(NULL);
7857 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7859 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7861 genIfxJump (ifx,"a");
7865 pic16_outBitC(result);
7869 /* if left is same as result */
7870 if(pic16_sameRegs(AOP(result),AOP(left))){
7872 for(;size--; offset++,lit>>=8) {
7873 if(AOP_TYPE(right) == AOP_LIT){
7874 if((lit & 0xff) == 0)
7875 /* or'ing with 0 has no effect */
7878 int p = pic16_my_powof2(lit & 0xff);
7880 /* only one bit is set in the literal, so use a bsf instruction */
7881 pic16_emitpcode(POC_BSF,
7882 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7884 if(know_W != (lit & 0xff))
7885 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7886 know_W = lit & 0xff;
7887 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7892 if (AOP_TYPE(left) == AOP_ACC) {
7893 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7894 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7896 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7897 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7899 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7900 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7906 // left & result in different registers
7907 if(AOP_TYPE(result) == AOP_CRY){
7909 // if(size), result in bit
7910 // if(!size && ifx), conditional oper: if(left | right)
7911 symbol *tlbl = newiTempLabel(NULL);
7912 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7913 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7917 pic16_emitcode(";XXX setb","c");
7919 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7920 pic16_emitcode(";XXX orl","a,%s",
7921 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7922 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7927 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7928 pic16_outBitC(result);
7930 jmpTrueOrFalse(ifx, tlbl);
7931 } else for(;(size--);offset++){
7933 // result = left & right
7934 if(AOP_TYPE(right) == AOP_LIT){
7935 int t = (lit >> (offset*8)) & 0x0FFL;
7938 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7939 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7941 pic16_emitcode("movf","%s,w",
7942 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7943 pic16_emitcode("movwf","%s",
7944 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7947 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7948 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7949 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7951 pic16_emitcode("movlw","0x%x",t);
7952 pic16_emitcode("iorwf","%s,w",
7953 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7954 pic16_emitcode("movwf","%s",
7955 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7961 // faster than result <- left, anl result,right
7962 // and better if result is SFR
7963 if (AOP_TYPE(left) == AOP_ACC) {
7964 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7965 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7967 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7968 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7970 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7971 pic16_emitcode("iorwf","%s,w",
7972 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7974 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7975 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7980 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7981 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7982 pic16_freeAsmop(result,NULL,ic,TRUE);
7985 /*-----------------------------------------------------------------*/
7986 /* genXor - code for xclusive or */
7987 /*-----------------------------------------------------------------*/
7988 static void genXor (iCode *ic, iCode *ifx)
7990 operand *left, *right, *result;
7992 unsigned long lit = 0L;
7994 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7996 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7997 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7998 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8000 /* if left is a literal & right is not ||
8001 if left needs acc & right does not */
8002 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8003 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8004 operand *tmp = right ;
8009 /* if result = right then exchange them */
8010 if(pic16_sameRegs(AOP(result),AOP(right))){
8011 operand *tmp = right ;
8016 /* if right is bit then exchange them */
8017 if (AOP_TYPE(right) == AOP_CRY &&
8018 AOP_TYPE(left) != AOP_CRY){
8019 operand *tmp = right ;
8023 if(AOP_TYPE(right) == AOP_LIT)
8024 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8026 size = AOP_SIZE(result);
8030 if (AOP_TYPE(left) == AOP_CRY){
8031 if(AOP_TYPE(right) == AOP_LIT){
8032 // c = bit & literal;
8034 // lit>>1 != 0 => result = 1
8035 if(AOP_TYPE(result) == AOP_CRY){
8037 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8038 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8040 continueIfTrue(ifx);
8043 pic16_emitcode("setb","c");
8047 // lit == 0, result = left
8048 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8050 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8052 // lit == 1, result = not(left)
8053 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8054 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8055 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8056 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8059 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8060 pic16_emitcode("cpl","c");
8067 symbol *tlbl = newiTempLabel(NULL);
8068 if (AOP_TYPE(right) == AOP_CRY){
8070 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8073 int sizer = AOP_SIZE(right);
8075 // if val>>1 != 0, result = 1
8076 pic16_emitcode("setb","c");
8078 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8080 // test the msb of the lsb
8081 pic16_emitcode("anl","a,#0xfe");
8082 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8086 pic16_emitcode("rrc","a");
8088 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8089 pic16_emitcode("cpl","c");
8090 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8095 pic16_outBitC(result);
8097 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8098 genIfxJump(ifx, "c");
8102 if(pic16_sameRegs(AOP(result),AOP(left))){
8103 /* if left is same as result */
8104 for(;size--; offset++) {
8105 if(AOP_TYPE(right) == AOP_LIT){
8106 int t = (lit >> (offset*8)) & 0x0FFL;
8110 if (IS_AOP_PREG(left)) {
8111 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8112 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8113 pic16_aopPut(AOP(result),"a",offset);
8115 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8116 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8117 pic16_emitcode("xrl","%s,%s",
8118 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8119 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8122 if (AOP_TYPE(left) == AOP_ACC)
8123 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8125 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8126 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8128 if (IS_AOP_PREG(left)) {
8129 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8130 pic16_aopPut(AOP(result),"a",offset);
8132 pic16_emitcode("xrl","%s,a",
8133 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8139 // left & result in different registers
8140 if(AOP_TYPE(result) == AOP_CRY){
8142 // if(size), result in bit
8143 // if(!size && ifx), conditional oper: if(left ^ right)
8144 symbol *tlbl = newiTempLabel(NULL);
8145 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8147 pic16_emitcode("setb","c");
8149 if((AOP_TYPE(right) == AOP_LIT) &&
8150 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8151 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8153 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8154 pic16_emitcode("xrl","a,%s",
8155 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8157 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8162 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8163 pic16_outBitC(result);
8165 jmpTrueOrFalse(ifx, tlbl);
8166 } else for(;(size--);offset++){
8168 // result = left & right
8169 if(AOP_TYPE(right) == AOP_LIT){
8170 int t = (lit >> (offset*8)) & 0x0FFL;
8173 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8174 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8175 pic16_emitcode("movf","%s,w",
8176 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8177 pic16_emitcode("movwf","%s",
8178 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8181 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8182 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8183 pic16_emitcode("comf","%s,w",
8184 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8185 pic16_emitcode("movwf","%s",
8186 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8189 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8190 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8191 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8192 pic16_emitcode("movlw","0x%x",t);
8193 pic16_emitcode("xorwf","%s,w",
8194 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8195 pic16_emitcode("movwf","%s",
8196 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8202 // faster than result <- left, anl result,right
8203 // and better if result is SFR
8204 if (AOP_TYPE(left) == AOP_ACC) {
8205 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8206 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8208 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8209 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8210 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8211 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8213 if ( AOP_TYPE(result) != AOP_ACC){
8214 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8215 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8221 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8222 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8223 pic16_freeAsmop(result,NULL,ic,TRUE);
8226 /*-----------------------------------------------------------------*/
8227 /* genInline - write the inline code out */
8228 /*-----------------------------------------------------------------*/
8229 static void genInline (iCode *ic)
8231 char *buffer, *bp, *bp1;
8233 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8235 _G.inLine += (!options.asmpeep);
8237 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8238 strcpy(buffer,IC_INLINE(ic));
8240 while((bp1=strstr(bp, "\\n"))) {
8248 /* This is an experimental code for #pragma inline
8249 and is temporarily disabled for 2.5.0 release */
8257 cbuf = Safe_strdup(buffer);
8258 cblen = strlen(buffer)+1;
8259 memset(cbuf, 0, cblen);
8264 if(*bp != '%')*bp1++ = *bp++;
8270 if(i>elementsInSet(asmInlineMap))break;
8273 s = indexSet(asmInlineMap, i);
8274 DEBUGpc("searching symbol s = `%s'", s);
8275 sym = findSym(SymbolTab, NULL, s);
8278 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8280 strcat(bp1, sym->rname);
8286 if(strlen(bp1) > cblen - 16) {
8287 int i = strlen(cbuf);
8289 cbuf = realloc(cbuf, cblen);
8290 memset(cbuf+i, 0, 50);
8296 buffer = Safe_strdup( cbuf );
8303 /* emit each line as a code */
8309 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8317 /* print label, use this special format with NULL directive
8318 * to denote that the argument should not be indented with tab */
8319 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8326 if ((bp1 != bp) && *bp1)
8327 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8332 _G.inLine -= (!options.asmpeep);
8335 /*-----------------------------------------------------------------*/
8336 /* genRRC - rotate right with carry */
8337 /*-----------------------------------------------------------------*/
8338 static void genRRC (iCode *ic)
8340 operand *left , *result ;
8341 int size, offset = 0, same;
8343 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8345 /* rotate right with carry */
8347 result=IC_RESULT(ic);
8348 pic16_aopOp (left,ic,FALSE);
8349 pic16_aopOp (result,ic,TRUE);
8351 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8353 same = pic16_sameRegs(AOP(result),AOP(left));
8355 size = AOP_SIZE(result);
8357 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8359 /* get the lsb and put it into the carry */
8360 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8367 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8369 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8370 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8376 pic16_freeAsmop(left,NULL,ic,TRUE);
8377 pic16_freeAsmop(result,NULL,ic,TRUE);
8380 /*-----------------------------------------------------------------*/
8381 /* genRLC - generate code for rotate left with carry */
8382 /*-----------------------------------------------------------------*/
8383 static void genRLC (iCode *ic)
8385 operand *left , *result ;
8386 int size, offset = 0;
8389 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8390 /* rotate right with carry */
8392 result=IC_RESULT(ic);
8393 pic16_aopOp (left,ic,FALSE);
8394 pic16_aopOp (result,ic,TRUE);
8396 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8398 same = pic16_sameRegs(AOP(result),AOP(left));
8400 /* move it to the result */
8401 size = AOP_SIZE(result);
8403 /* get the msb and put it into the carry */
8404 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8411 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8413 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8414 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8421 pic16_freeAsmop(left,NULL,ic,TRUE);
8422 pic16_freeAsmop(result,NULL,ic,TRUE);
8426 /* gpasm can get the highest order bit with HIGH/UPPER
8427 * so the following probably is not needed -- VR */
8429 /*-----------------------------------------------------------------*/
8430 /* genGetHbit - generates code get highest order bit */
8431 /*-----------------------------------------------------------------*/
8432 static void genGetHbit (iCode *ic)
8434 operand *left, *result;
8436 result=IC_RESULT(ic);
8437 pic16_aopOp (left,ic,FALSE);
8438 pic16_aopOp (result,ic,FALSE);
8440 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8441 /* get the highest order byte into a */
8442 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8443 if(AOP_TYPE(result) == AOP_CRY){
8444 pic16_emitcode("rlc","a");
8445 pic16_outBitC(result);
8448 pic16_emitcode("rl","a");
8449 pic16_emitcode("anl","a,#0x01");
8450 pic16_outAcc(result);
8454 pic16_freeAsmop(left,NULL,ic,TRUE);
8455 pic16_freeAsmop(result,NULL,ic,TRUE);
8459 /*-----------------------------------------------------------------*/
8460 /* AccRol - rotate left accumulator by known count */
8461 /*-----------------------------------------------------------------*/
8462 static void AccRol (int shCount)
8464 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8465 shCount &= 0x0007; // shCount : 0..7
8470 pic16_emitcode("rl","a");
8473 pic16_emitcode("rl","a");
8474 pic16_emitcode("rl","a");
8477 pic16_emitcode("swap","a");
8478 pic16_emitcode("rr","a");
8481 pic16_emitcode("swap","a");
8484 pic16_emitcode("swap","a");
8485 pic16_emitcode("rl","a");
8488 pic16_emitcode("rr","a");
8489 pic16_emitcode("rr","a");
8492 pic16_emitcode("rr","a");
8498 /*-----------------------------------------------------------------*/
8499 /* AccLsh - left shift accumulator by known count */
8500 /*-----------------------------------------------------------------*/
8501 static void AccLsh (int shCount)
8503 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8509 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8512 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8513 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8516 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8517 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8520 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8523 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8524 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8527 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8528 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8531 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8535 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8538 /*-----------------------------------------------------------------*/
8539 /* AccRsh - right shift accumulator by known count */
8540 /*-----------------------------------------------------------------*/
8541 static void AccRsh (int shCount, int andmask)
8543 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8548 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8551 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8552 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8555 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8556 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8559 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8562 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8563 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8566 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8567 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8570 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8575 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8577 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8581 /*-----------------------------------------------------------------*/
8582 /* AccSRsh - signed right shift accumulator by known count */
8583 /*-----------------------------------------------------------------*/
8584 static void AccSRsh (int shCount)
8587 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8590 pic16_emitcode("mov","c,acc.7");
8591 pic16_emitcode("rrc","a");
8592 } else if(shCount == 2){
8593 pic16_emitcode("mov","c,acc.7");
8594 pic16_emitcode("rrc","a");
8595 pic16_emitcode("mov","c,acc.7");
8596 pic16_emitcode("rrc","a");
8598 tlbl = newiTempLabel(NULL);
8599 /* rotate right accumulator */
8600 AccRol(8 - shCount);
8601 /* and kill the higher order bits */
8602 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8603 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8604 pic16_emitcode("orl","a,#0x%02x",
8605 (unsigned char)~SRMask[shCount]);
8606 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8612 /*-----------------------------------------------------------------*/
8613 /* shiftR1Left2Result - shift right one byte from left to result */
8614 /*-----------------------------------------------------------------*/
8615 static void shiftR1Left2ResultSigned (operand *left, int offl,
8616 operand *result, int offr,
8621 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8623 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8627 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8629 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8631 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8632 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8638 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8640 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8642 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8643 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8645 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8646 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8652 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8654 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8655 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8658 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8659 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8660 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8662 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8663 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8665 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8669 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8670 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8671 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8672 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8673 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8677 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8679 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8680 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8682 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8683 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8684 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8685 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8686 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8691 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8692 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8693 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8694 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8695 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8696 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8698 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8699 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8700 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8701 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8702 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8708 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8709 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8710 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8711 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8713 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8714 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8715 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8723 /*-----------------------------------------------------------------*/
8724 /* shiftR1Left2Result - shift right one byte from left to result */
8725 /*-----------------------------------------------------------------*/
8726 static void shiftR1Left2Result (operand *left, int offl,
8727 operand *result, int offr,
8728 int shCount, int sign)
8732 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8734 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8736 /* Copy the msb into the carry if signed. */
8738 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8748 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8750 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8751 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8757 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8759 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8760 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8763 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8768 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8770 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8771 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8774 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8775 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8776 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8777 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8781 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8782 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8783 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8787 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8788 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8789 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8791 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8796 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8797 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8798 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8799 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8800 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8805 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8806 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8807 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8816 /*-----------------------------------------------------------------*/
8817 /* shiftL1Left2Result - shift left one byte from left to result */
8818 /*-----------------------------------------------------------------*/
8819 static void shiftL1Left2Result (operand *left, int offl,
8820 operand *result, int offr, int shCount)
8825 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8827 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8828 DEBUGpic16_emitcode ("; ***","same = %d",same);
8829 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8831 /* shift left accumulator */
8832 //AccLsh(shCount); // don't comment out just yet...
8833 // pic16_aopPut(AOP(result),"a",offr);
8837 /* Shift left 1 bit position */
8838 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8840 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8842 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8843 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8847 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8848 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8849 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8850 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8853 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8854 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8855 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8856 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8857 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8860 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8861 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8862 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8865 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8866 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8867 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8868 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8871 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8872 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8873 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8874 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8875 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8878 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8879 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8880 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8884 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8889 /*-----------------------------------------------------------------*/
8890 /* movLeft2Result - move byte from left to result */
8891 /*-----------------------------------------------------------------*/
8892 static void movLeft2Result (operand *left, int offl,
8893 operand *result, int offr)
8896 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8897 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8898 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8900 if (*l == '@' && (IS_AOP_PREG(result))) {
8901 pic16_emitcode("mov","a,%s",l);
8902 pic16_aopPut(AOP(result),"a",offr);
8904 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8905 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8910 /*-----------------------------------------------------------------*/
8911 /* shiftL2Left2Result - shift left two bytes from left to result */
8912 /*-----------------------------------------------------------------*/
8913 static void shiftL2Left2Result (operand *left, int offl,
8914 operand *result, int offr, int shCount)
8916 int same = pic16_sameRegs(AOP(result), AOP(left));
8919 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8921 if (same && (offl != offr)) { // shift bytes
8924 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8925 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8927 } else { // just treat as different later on
8940 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8941 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8942 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8946 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8947 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8953 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8954 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8955 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8956 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8957 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8958 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8959 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8961 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8962 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8966 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8967 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8968 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8969 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8970 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8971 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8972 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8973 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8974 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8975 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8978 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8979 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8980 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8981 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8982 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8992 /* note, use a mov/add for the shift since the mov has a
8993 chance of getting optimized out */
8994 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8995 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8996 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8997 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8998 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9002 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9003 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9009 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9010 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9011 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9012 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9013 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9014 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9015 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9016 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9020 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9021 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9025 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9026 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9027 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9028 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9030 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9031 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9032 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9033 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9034 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9035 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9036 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9037 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9040 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9041 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9042 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9043 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9044 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9049 /*-----------------------------------------------------------------*/
9050 /* shiftR2Left2Result - shift right two bytes from left to result */
9051 /*-----------------------------------------------------------------*/
9052 static void shiftR2Left2Result (operand *left, int offl,
9053 operand *result, int offr,
9054 int shCount, int sign)
9056 int same = pic16_sameRegs(AOP(result), AOP(left));
9058 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9060 if (same && (offl != offr)) { // shift right bytes
9063 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9064 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9066 } else { // just treat as different later on
9078 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9083 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9084 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9086 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9087 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9088 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9089 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9094 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9097 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9098 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9105 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9106 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9107 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9109 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9110 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9111 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9112 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9114 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9115 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9116 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9118 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9119 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9120 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9121 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9122 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9126 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9127 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9131 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9132 pic16_emitpcode(POC_BTFSC,
9133 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9134 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9142 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9143 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9145 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9146 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9147 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9148 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9150 pic16_emitpcode(POC_BTFSC,
9151 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9152 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9154 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9155 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9156 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9157 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9159 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9160 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9161 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9162 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9163 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9164 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9165 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9166 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9168 pic16_emitpcode(POC_BTFSC,
9169 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9170 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9172 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9173 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9180 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9181 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9182 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9183 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9186 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9188 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9193 /*-----------------------------------------------------------------*/
9194 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9195 /*-----------------------------------------------------------------*/
9196 static void shiftLLeftOrResult (operand *left, int offl,
9197 operand *result, int offr, int shCount)
9199 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9201 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9202 /* shift left accumulator */
9204 /* or with result */
9205 /* back to result */
9206 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9209 /*-----------------------------------------------------------------*/
9210 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9211 /*-----------------------------------------------------------------*/
9212 static void shiftRLeftOrResult (operand *left, int offl,
9213 operand *result, int offr, int shCount)
9215 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9217 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9218 /* shift right accumulator */
9220 /* or with result */
9221 /* back to result */
9222 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9225 /*-----------------------------------------------------------------*/
9226 /* genlshOne - left shift a one byte quantity by known count */
9227 /*-----------------------------------------------------------------*/
9228 static void genlshOne (operand *result, operand *left, int shCount)
9230 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9231 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9234 /*-----------------------------------------------------------------*/
9235 /* genlshTwo - left shift two bytes by known amount != 0 */
9236 /*-----------------------------------------------------------------*/
9237 static void genlshTwo (operand *result,operand *left, int shCount)
9241 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9242 size = pic16_getDataSize(result);
9244 /* if shCount >= 8 */
9250 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9252 movLeft2Result(left, LSB, result, MSB16);
9254 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9257 /* 1 <= shCount <= 7 */
9260 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9262 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9266 /*-----------------------------------------------------------------*/
9267 /* shiftLLong - shift left one long from left to result */
9268 /* offr = LSB or MSB16 */
9269 /*-----------------------------------------------------------------*/
9270 static void shiftLLong (operand *left, operand *result, int offr )
9272 int size = AOP_SIZE(result);
9273 int same = pic16_sameRegs(AOP(left),AOP(result));
9276 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9278 if (same && (offr == MSB16)) { //shift one byte
9279 for(i=size-1;i>=MSB16;i--) {
9280 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9281 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9284 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9287 if (size > LSB+offr ){
9289 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9291 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9292 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9296 if(size > MSB16+offr){
9298 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9300 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9301 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9305 if(size > MSB24+offr){
9307 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9309 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9310 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9314 if(size > MSB32+offr){
9316 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9318 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9319 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9323 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9327 /*-----------------------------------------------------------------*/
9328 /* genlshFour - shift four byte by a known amount != 0 */
9329 /*-----------------------------------------------------------------*/
9330 static void genlshFour (operand *result, operand *left, int shCount)
9334 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9335 size = AOP_SIZE(result);
9337 /* if shifting more that 3 bytes */
9338 if (shCount >= 24 ) {
9341 /* lowest order of left goes to the highest
9342 order of the destination */
9343 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9345 movLeft2Result(left, LSB, result, MSB32);
9347 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9348 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9349 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9354 /* more than two bytes */
9355 else if ( shCount >= 16 ) {
9356 /* lower order two bytes goes to higher order two bytes */
9358 /* if some more remaining */
9360 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9362 movLeft2Result(left, MSB16, result, MSB32);
9363 movLeft2Result(left, LSB, result, MSB24);
9365 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9366 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9370 /* if more than 1 byte */
9371 else if ( shCount >= 8 ) {
9372 /* lower order three bytes goes to higher order three bytes */
9376 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9378 movLeft2Result(left, LSB, result, MSB16);
9380 else{ /* size = 4 */
9382 movLeft2Result(left, MSB24, result, MSB32);
9383 movLeft2Result(left, MSB16, result, MSB24);
9384 movLeft2Result(left, LSB, result, MSB16);
9385 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9387 else if(shCount == 1)
9388 shiftLLong(left, result, MSB16);
9390 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9391 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9392 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9393 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9398 /* 1 <= shCount <= 7 */
9399 else if(shCount <= 3)
9401 shiftLLong(left, result, LSB);
9402 while(--shCount >= 1)
9403 shiftLLong(result, result, LSB);
9405 /* 3 <= shCount <= 7, optimize */
9407 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9408 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9409 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9413 /*-----------------------------------------------------------------*/
9414 /* genLeftShiftLiteral - left shifting by known count */
9415 /*-----------------------------------------------------------------*/
9416 void pic16_genLeftShiftLiteral (operand *left,
9421 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9425 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9426 pic16_freeAsmop(right,NULL,ic,TRUE);
9428 pic16_aopOp(left,ic,FALSE);
9429 pic16_aopOp(result,ic,TRUE);
9431 size = getSize(operandType(result));
9434 pic16_emitcode("; shift left ","result %d, left %d",size,
9438 /* I suppose that the left size >= result size */
9441 movLeft2Result(left, size, result, size);
9445 else if(shCount >= (size * 8))
9447 pic16_aopPut(AOP(result),zero,size);
9451 genlshOne (result,left,shCount);
9456 genlshTwo (result,left,shCount);
9460 genlshFour (result,left,shCount);
9464 pic16_freeAsmop(left,NULL,ic,TRUE);
9465 pic16_freeAsmop(result,NULL,ic,TRUE);
9468 /*-----------------------------------------------------------------*
9469 * genMultiAsm - repeat assembly instruction for size of register.
9470 * if endian == 1, then the high byte (i.e base address + size of
9471 * register) is used first else the low byte is used first;
9472 *-----------------------------------------------------------------*/
9473 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9478 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9491 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9497 #if !(USE_GENERIC_SIGNED_SHIFT)
9498 /*-----------------------------------------------------------------*/
9499 /* genLeftShift - generates code for left shifting */
9500 /*-----------------------------------------------------------------*/
9501 static void genLeftShift (iCode *ic)
9503 operand *left,*right, *result;
9506 symbol *tlbl , *tlbl1;
9509 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9511 right = IC_RIGHT(ic);
9513 result = IC_RESULT(ic);
9515 pic16_aopOp(right,ic,FALSE);
9517 /* if the shift count is known then do it
9518 as efficiently as possible */
9519 if (AOP_TYPE(right) == AOP_LIT) {
9520 pic16_genLeftShiftLiteral (left,right,result,ic);
9524 /* shift count is unknown then we have to form
9525 * a loop. Get the loop count in WREG : Note: we take
9526 * only the lower order byte since shifting
9527 * more than 32 bits make no sense anyway, ( the
9528 * largest size of an object can be only 32 bits ) */
9530 pic16_aopOp(left,ic,FALSE);
9531 pic16_aopOp(result,ic,FALSE);
9533 /* now move the left to the result if they are not the
9534 * same, and if size > 1,
9535 * and if right is not same to result (!!!) -- VR */
9536 if (!pic16_sameRegs(AOP(left),AOP(result))
9537 && (AOP_SIZE(result) > 1)) {
9539 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9541 size = AOP_SIZE(result);
9546 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9547 if (*l == '@' && (IS_AOP_PREG(result))) {
9549 pic16_emitcode("mov","a,%s",l);
9550 pic16_aopPut(AOP(result),"a",offset);
9554 /* we don't know if left is a literal or a register, take care -- VR */
9555 pic16_mov2f(AOP(result), AOP(left), offset);
9561 size = AOP_SIZE(result);
9563 /* if it is only one byte then */
9565 if(optimized_for_speed) {
9566 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9567 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9568 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9569 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9570 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9571 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9572 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9573 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9574 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9575 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9576 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9577 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9580 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9582 tlbl = newiTempLabel(NULL);
9585 /* this is already done, why change it? */
9586 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9587 pic16_mov2f(AOP(result), AOP(left), 0);
9591 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9592 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9593 pic16_emitpLabel(tlbl->key);
9594 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9595 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9597 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9602 if (pic16_sameRegs(AOP(left),AOP(result))) {
9604 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9606 tlbl = newiTempLabel(NULL);
9607 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9608 genMultiAsm(POC_RRCF, result, size,1);
9609 pic16_emitpLabel(tlbl->key);
9610 genMultiAsm(POC_RLCF, result, size,0);
9611 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9613 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9617 //tlbl = newiTempLabel(NULL);
9619 //tlbl1 = newiTempLabel(NULL);
9621 //reAdjustPreg(AOP(result));
9623 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9624 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9625 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9627 //pic16_emitcode("add","a,acc");
9628 //pic16_aopPut(AOP(result),"a",offset++);
9630 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9632 // pic16_emitcode("rlc","a");
9633 // pic16_aopPut(AOP(result),"a",offset++);
9635 //reAdjustPreg(AOP(result));
9637 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9638 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9641 tlbl = newiTempLabel(NULL);
9642 tlbl1= newiTempLabel(NULL);
9644 size = AOP_SIZE(result);
9647 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9649 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9651 /* offset should be 0, 1 or 3 */
9653 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9655 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9657 pic16_emitpcode(POC_MOVWF, pctemp);
9660 pic16_emitpLabel(tlbl->key);
9663 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9665 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9667 pic16_emitpcode(POC_DECFSZ, pctemp);
9668 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9669 pic16_emitpLabel(tlbl1->key);
9671 pic16_popReleaseTempReg(pctemp,1);
9675 pic16_freeAsmop (right,NULL,ic,TRUE);
9676 pic16_freeAsmop(left,NULL,ic,TRUE);
9677 pic16_freeAsmop(result,NULL,ic,TRUE);
9683 #error old code (left here for reference)
9684 /*-----------------------------------------------------------------*/
9685 /* genLeftShift - generates code for left shifting */
9686 /*-----------------------------------------------------------------*/
9687 static void genLeftShift (iCode *ic)
9689 operand *left,*right, *result;
9692 symbol *tlbl , *tlbl1;
9695 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9697 right = IC_RIGHT(ic);
9699 result = IC_RESULT(ic);
9701 pic16_aopOp(right,ic,FALSE);
9703 /* if the shift count is known then do it
9704 as efficiently as possible */
9705 if (AOP_TYPE(right) == AOP_LIT) {
9706 pic16_genLeftShiftLiteral (left,right,result,ic);
9710 /* shift count is unknown then we have to form
9711 a loop get the loop count in B : Note: we take
9712 only the lower order byte since shifting
9713 more that 32 bits make no sense anyway, ( the
9714 largest size of an object can be only 32 bits ) */
9717 pic16_aopOp(left,ic,FALSE);
9718 pic16_aopOp(result,ic,FALSE);
9720 /* now move the left to the result if they are not the
9722 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9723 AOP_SIZE(result) > 1) {
9725 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9727 size = AOP_SIZE(result);
9730 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9731 if (*l == '@' && (IS_AOP_PREG(result))) {
9733 pic16_emitcode("mov","a,%s",l);
9734 pic16_aopPut(AOP(result),"a",offset);
9737 /* we don't know if left is a literal or a register, take care -- VR */
9738 pic16_mov2f(AOP(result), AOP(left), offset);
9744 size = AOP_SIZE(result);
9746 /* if it is only one byte then */
9748 if(optimized_for_speed) {
9749 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9750 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9751 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9752 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9753 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9754 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9755 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9756 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9757 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9758 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9759 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9760 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9763 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9765 tlbl = newiTempLabel(NULL);
9766 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9767 pic16_mov2f(AOP(result), AOP(left), 0);
9769 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9770 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9773 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9774 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9775 pic16_emitpLabel(tlbl->key);
9776 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9777 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9779 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9784 if (pic16_sameRegs(AOP(left),AOP(result))) {
9786 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9788 tlbl = newiTempLabel(NULL);
9789 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9790 genMultiAsm(POC_RRCF, result, size,1);
9791 pic16_emitpLabel(tlbl->key);
9792 genMultiAsm(POC_RLCF, result, size,0);
9793 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9795 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9799 //tlbl = newiTempLabel(NULL);
9801 //tlbl1 = newiTempLabel(NULL);
9803 //reAdjustPreg(AOP(result));
9805 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9806 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9807 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9809 //pic16_emitcode("add","a,acc");
9810 //pic16_aopPut(AOP(result),"a",offset++);
9812 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9814 // pic16_emitcode("rlc","a");
9815 // pic16_aopPut(AOP(result),"a",offset++);
9817 //reAdjustPreg(AOP(result));
9819 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9820 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9823 tlbl = newiTempLabel(NULL);
9824 tlbl1= newiTempLabel(NULL);
9826 size = AOP_SIZE(result);
9829 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9831 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9833 /* offset should be 0, 1 or 3 */
9835 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9837 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9839 pic16_emitpcode(POC_MOVWF, pctemp);
9842 pic16_emitpLabel(tlbl->key);
9845 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9847 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9849 pic16_emitpcode(POC_DECFSZ, pctemp);
9850 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9851 pic16_emitpLabel(tlbl1->key);
9853 pic16_popReleaseTempReg(pctemp,1);
9857 pic16_freeAsmop (right,NULL,ic,TRUE);
9858 pic16_freeAsmop(left,NULL,ic,TRUE);
9859 pic16_freeAsmop(result,NULL,ic,TRUE);
9863 /*-----------------------------------------------------------------*/
9864 /* genrshOne - right shift a one byte quantity by known count */
9865 /*-----------------------------------------------------------------*/
9866 static void genrshOne (operand *result, operand *left,
9867 int shCount, int sign)
9869 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9870 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9873 /*-----------------------------------------------------------------*/
9874 /* genrshTwo - right shift two bytes by known amount != 0 */
9875 /*-----------------------------------------------------------------*/
9876 static void genrshTwo (operand *result,operand *left,
9877 int shCount, int sign)
9879 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9880 /* if shCount >= 8 */
9884 shiftR1Left2Result(left, MSB16, result, LSB,
9887 movLeft2Result(left, MSB16, result, LSB);
9889 pic16_addSign (result, 1, sign);
9892 /* 1 <= shCount <= 7 */
9894 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9897 /*-----------------------------------------------------------------*/
9898 /* shiftRLong - shift right one long from left to result */
9899 /* offl = LSB or MSB16 */
9900 /*-----------------------------------------------------------------*/
9901 static void shiftRLong (operand *left, int offl,
9902 operand *result, int sign)
9904 int size = AOP_SIZE(result);
9905 int same = pic16_sameRegs(AOP(left),AOP(result));
9907 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9909 if (same && (offl == MSB16)) { //shift one byte right
9910 for(i=MSB16;i<size;i++) {
9911 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9912 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9917 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9923 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9925 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9926 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9930 /* add sign of "a" */
9931 pic16_addSign(result, MSB32, sign);
9935 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9937 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9938 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9942 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9944 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9945 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9949 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9952 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9953 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9958 /*-----------------------------------------------------------------*/
9959 /* genrshFour - shift four byte by a known amount != 0 */
9960 /*-----------------------------------------------------------------*/
9961 static void genrshFour (operand *result, operand *left,
9962 int shCount, int sign)
9964 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9965 /* if shifting more that 3 bytes */
9966 if(shCount >= 24 ) {
9969 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9971 movLeft2Result(left, MSB32, result, LSB);
9973 pic16_addSign(result, MSB16, sign);
9975 else if(shCount >= 16){
9978 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9980 movLeft2Result(left, MSB24, result, LSB);
9981 movLeft2Result(left, MSB32, result, MSB16);
9983 pic16_addSign(result, MSB24, sign);
9985 else if(shCount >= 8){
9988 shiftRLong(left, MSB16, result, sign);
9989 else if(shCount == 0){
9990 movLeft2Result(left, MSB16, result, LSB);
9991 movLeft2Result(left, MSB24, result, MSB16);
9992 movLeft2Result(left, MSB32, result, MSB24);
9993 pic16_addSign(result, MSB32, sign);
9995 else{ //shcount >= 2
9996 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9997 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9998 /* the last shift is signed */
9999 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10000 pic16_addSign(result, MSB32, sign);
10003 else{ /* 1 <= shCount <= 7 */
10005 shiftRLong(left, LSB, result, sign);
10007 shiftRLong(result, LSB, result, sign);
10010 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10011 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10012 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10017 /*-----------------------------------------------------------------*/
10018 /* genRightShiftLiteral - right shifting by known count */
10019 /*-----------------------------------------------------------------*/
10020 static void genRightShiftLiteral (operand *left,
10026 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10027 int lsize,res_size;
10029 pic16_freeAsmop(right,NULL,ic,TRUE);
10031 pic16_aopOp(left,ic,FALSE);
10032 pic16_aopOp(result,ic,TRUE);
10034 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10037 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10041 lsize = pic16_getDataSize(left);
10042 res_size = pic16_getDataSize(result);
10043 /* test the LEFT size !!! */
10045 /* I suppose that the left size >= result size */
10047 assert (res_size <= lsize);
10048 while (res_size--) {
10049 pic16_mov2f (AOP(result), AOP(left), res_size);
10053 else if(shCount >= (lsize * 8)){
10055 if(res_size == 1) {
10056 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10058 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10059 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10064 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10065 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10066 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10068 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10073 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10078 switch (res_size) {
10080 genrshOne (result,left,shCount,sign);
10084 genrshTwo (result,left,shCount,sign);
10088 genrshFour (result,left,shCount,sign);
10096 pic16_freeAsmop(left,NULL,ic,TRUE);
10097 pic16_freeAsmop(result,NULL,ic,TRUE);
10100 #if !(USE_GENERIC_SIGNED_SHIFT)
10101 /*-----------------------------------------------------------------*/
10102 /* genSignedRightShift - right shift of signed number */
10103 /*-----------------------------------------------------------------*/
10104 static void genSignedRightShift (iCode *ic)
10106 operand *right, *left, *result;
10109 symbol *tlbl, *tlbl1 ;
10112 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10114 /* we do it the hard way put the shift count in b
10115 and loop thru preserving the sign */
10116 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10118 right = IC_RIGHT(ic);
10119 left = IC_LEFT(ic);
10120 result = IC_RESULT(ic);
10122 pic16_aopOp(right,ic,FALSE);
10123 pic16_aopOp(left,ic,FALSE);
10124 pic16_aopOp(result,ic,FALSE);
10127 if ( AOP_TYPE(right) == AOP_LIT) {
10128 genRightShiftLiteral (left,right,result,ic,1);
10131 /* shift count is unknown then we have to form
10132 a loop get the loop count in B : Note: we take
10133 only the lower order byte since shifting
10134 more that 32 bits make no sense anyway, ( the
10135 largest size of an object can be only 32 bits ) */
10137 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10138 //pic16_emitcode("inc","b");
10139 //pic16_freeAsmop (right,NULL,ic,TRUE);
10140 //pic16_aopOp(left,ic,FALSE);
10141 //pic16_aopOp(result,ic,FALSE);
10143 /* now move the left to the result if they are not the
10145 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10146 AOP_SIZE(result) > 1) {
10148 size = AOP_SIZE(result);
10152 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10153 if (*l == '@' && IS_AOP_PREG(result)) {
10155 pic16_emitcode("mov","a,%s",l);
10156 pic16_aopPut(AOP(result),"a",offset);
10158 pic16_aopPut(AOP(result),l,offset);
10160 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10161 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10167 /* mov the highest order bit to OVR */
10168 tlbl = newiTempLabel(NULL);
10169 tlbl1= newiTempLabel(NULL);
10171 size = AOP_SIZE(result);
10174 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10176 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10178 /* offset should be 0, 1 or 3 */
10179 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10181 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10183 pic16_emitpcode(POC_MOVWF, pctemp);
10186 pic16_emitpLabel(tlbl->key);
10188 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10189 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10192 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10195 pic16_emitpcode(POC_DECFSZ, pctemp);
10196 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10197 pic16_emitpLabel(tlbl1->key);
10199 pic16_popReleaseTempReg(pctemp,1);
10201 size = AOP_SIZE(result);
10203 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10204 pic16_emitcode("rlc","a");
10205 pic16_emitcode("mov","ov,c");
10206 /* if it is only one byte then */
10208 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10210 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10211 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10212 pic16_emitcode("mov","c,ov");
10213 pic16_emitcode("rrc","a");
10214 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10215 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10216 pic16_aopPut(AOP(result),"a",0);
10220 reAdjustPreg(AOP(result));
10221 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10222 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10223 pic16_emitcode("mov","c,ov");
10225 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10227 pic16_emitcode("rrc","a");
10228 pic16_aopPut(AOP(result),"a",offset--);
10230 reAdjustPreg(AOP(result));
10231 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10232 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10237 pic16_freeAsmop(left,NULL,ic,TRUE);
10238 pic16_freeAsmop(result,NULL,ic,TRUE);
10239 pic16_freeAsmop(right,NULL,ic,TRUE);
10243 #if !(USE_GENERIC_SIGNED_SHIFT)
10244 #warning This implementation of genRightShift() is incomplete!
10245 /*-----------------------------------------------------------------*/
10246 /* genRightShift - generate code for right shifting */
10247 /*-----------------------------------------------------------------*/
10248 static void genRightShift (iCode *ic)
10250 operand *right, *left, *result;
10254 symbol *tlbl, *tlbl1 ;
10256 /* if signed then we do it the hard way preserve the
10257 sign bit moving it inwards */
10258 letype = getSpec(operandType(IC_LEFT(ic)));
10259 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10261 if (!SPEC_USIGN(letype)) {
10262 genSignedRightShift (ic);
10266 /* signed & unsigned types are treated the same : i.e. the
10267 signed is NOT propagated inwards : quoting from the
10268 ANSI - standard : "for E1 >> E2, is equivalent to division
10269 by 2**E2 if unsigned or if it has a non-negative value,
10270 otherwise the result is implementation defined ", MY definition
10271 is that the sign does not get propagated */
10273 right = IC_RIGHT(ic);
10274 left = IC_LEFT(ic);
10275 result = IC_RESULT(ic);
10277 pic16_aopOp(right,ic,FALSE);
10279 /* if the shift count is known then do it
10280 as efficiently as possible */
10281 if (AOP_TYPE(right) == AOP_LIT) {
10282 genRightShiftLiteral (left,right,result,ic, 0);
10286 /* shift count is unknown then we have to form
10287 a loop get the loop count in B : Note: we take
10288 only the lower order byte since shifting
10289 more that 32 bits make no sense anyway, ( the
10290 largest size of an object can be only 32 bits ) */
10292 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10293 pic16_emitcode("inc","b");
10294 pic16_aopOp(left,ic,FALSE);
10295 pic16_aopOp(result,ic,FALSE);
10297 /* now move the left to the result if they are not the
10299 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10300 AOP_SIZE(result) > 1) {
10302 size = AOP_SIZE(result);
10305 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10306 if (*l == '@' && IS_AOP_PREG(result)) {
10308 pic16_emitcode("mov","a,%s",l);
10309 pic16_aopPut(AOP(result),"a",offset);
10311 pic16_aopPut(AOP(result),l,offset);
10316 tlbl = newiTempLabel(NULL);
10317 tlbl1= newiTempLabel(NULL);
10318 size = AOP_SIZE(result);
10321 /* if it is only one byte then */
10324 tlbl = newiTempLabel(NULL);
10325 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10326 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10327 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10330 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10331 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10332 pic16_emitpLabel(tlbl->key);
10333 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10334 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10336 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10341 reAdjustPreg(AOP(result));
10342 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10343 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10346 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10348 pic16_emitcode("rrc","a");
10349 pic16_aopPut(AOP(result),"a",offset--);
10351 reAdjustPreg(AOP(result));
10353 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10354 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10357 pic16_freeAsmop(left,NULL,ic,TRUE);
10358 pic16_freeAsmop (right,NULL,ic,TRUE);
10359 pic16_freeAsmop(result,NULL,ic,TRUE);
10363 #if (USE_GENERIC_SIGNED_SHIFT)
10364 /*-----------------------------------------------------------------*/
10365 /* genGenericShift - generates code for left or right shifting */
10366 /*-----------------------------------------------------------------*/
10367 static void genGenericShift (iCode *ic, int isShiftLeft) {
10368 operand *left,*right, *result;
10370 int sign, signedCount;
10371 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10372 PIC_OPCODE pos_shift, neg_shift;
10376 right = IC_RIGHT(ic);
10377 left = IC_LEFT(ic);
10378 result = IC_RESULT(ic);
10380 pic16_aopOp(right,ic,FALSE);
10381 pic16_aopOp(left,ic,FALSE);
10382 pic16_aopOp(result,ic,TRUE);
10384 sign = !SPEC_USIGN(operandType (left));
10385 signedCount = !SPEC_USIGN(operandType (right));
10387 /* if the shift count is known then do it
10388 as efficiently as possible */
10389 if (AOP_TYPE(right) == AOP_LIT) {
10390 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10391 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10392 // we should modify right->aopu.aop_lit here!
10393 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10394 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10396 pic16_genLeftShiftLiteral (left,right,result,ic);
10398 genRightShiftLiteral (left,right,result,ic, sign);
10401 } // if (right is literal)
10403 /* shift count is unknown then we have to form a loop.
10404 * Note: we take only the lower order byte since shifting
10405 * more than 32 bits make no sense anyway, ( the
10406 * largest size of an object can be only 32 bits )
10407 * Note: we perform arithmetic shifts if the left operand is
10408 * signed and we do an (effective) right shift, i. e. we
10409 * shift in the sign bit from the left. */
10411 label_complete = newiTempLabel ( NULL );
10412 label_loop_pos = newiTempLabel ( NULL );
10413 label_loop_neg = NULL;
10414 label_negative = NULL;
10415 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10416 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10419 // additional labels needed
10420 label_loop_neg = newiTempLabel ( NULL );
10421 label_negative = newiTempLabel ( NULL );
10424 // copy source to result -- this will effectively truncate the left operand to the size of result!
10425 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10426 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10427 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10428 pic16_mov2f (AOP(result),AOP(left), offset);
10431 // if result is longer than left, fill with zeros (or sign)
10432 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10433 if (sign && AOP_SIZE(left) > 0) {
10434 // shift signed operand -- fill with sign
10435 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10436 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10437 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10438 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10439 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10442 // shift unsigned operand -- fill result with zeros
10443 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10444 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10447 } // if (size mismatch)
10449 pic16_mov2w (AOP(right), 0);
10450 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10451 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10454 // perform a shift by one (shift count is positive)
10455 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10456 // 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])
10457 pic16_emitpLabel (label_loop_pos->key);
10459 if (sign && (pos_shift == POC_RRCF)) {
10460 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10463 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10464 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10465 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10467 // perform a shift by one (shift count is positive)
10468 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10469 // 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])
10470 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10471 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10473 pic16_emitpLabel (label_loop_pos->key);
10474 if (sign && (pos_shift == POC_RRCF)) {
10475 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10478 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10479 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10480 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10481 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10485 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10487 pic16_emitpLabel (label_negative->key);
10488 // perform a shift by -1 (shift count is negative)
10489 // 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)
10491 pic16_emitpLabel (label_loop_neg->key);
10492 if (sign && (neg_shift == POC_RRCF)) {
10493 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10496 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10497 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10498 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10499 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10500 } // if (signedCount)
10502 pic16_emitpLabel (label_complete->key);
10505 pic16_freeAsmop (right,NULL,ic,TRUE);
10506 pic16_freeAsmop(left,NULL,ic,TRUE);
10507 pic16_freeAsmop(result,NULL,ic,TRUE);
10510 static void genLeftShift (iCode *ic) {
10511 genGenericShift (ic, 1);
10514 static void genRightShift (iCode *ic) {
10515 genGenericShift (ic, 0);
10520 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10521 void pic16_loadFSR0(operand *op, int lit)
10523 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10524 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10526 assert (!OP_SYMBOL(op)->remat);
10527 // set up FSR0 with address of result
10528 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10529 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10533 /*----------------------------------------------------------------*/
10534 /* pic16_derefPtr - move one byte from the location ptr points to */
10535 /* to WREG (doWrite == 0) or one byte from WREG */
10536 /* to the location ptr points to (doWrite != 0) */
10537 /*----------------------------------------------------------------*/
10538 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10543 if (!fsr0_setup || !*fsr0_setup)
10545 pic16_loadFSR0( ptr, 0 );
10546 if (fsr0_setup) *fsr0_setup = 1;
10549 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10551 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10555 if (AOP(ptr)->aopu.aop_reg[2]) {
10556 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10557 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10558 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10559 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl)));
10560 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(ptr),2));
10561 pic16_callGenericPointerRW(doWrite, 1);
10563 // data pointer (just 2 byte given)
10564 if (!fsr0_setup || !*fsr0_setup)
10566 pic16_loadFSR0( ptr, 0 );
10567 if (fsr0_setup) *fsr0_setup = 1;
10570 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10572 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10577 assert (0 && "invalid pointer type specified");
10582 /*-----------------------------------------------------------------*/
10583 /* genUnpackBits - generates code for unpacking bits */
10584 /*-----------------------------------------------------------------*/
10585 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10588 sym_link *etype, *letype;
10589 int blen=0, bstr=0;
10592 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10593 etype = getSpec(operandType(result));
10594 letype = getSpec(operandType(left));
10596 // if(IS_BITFIELD(etype)) {
10597 blen = SPEC_BLEN(etype);
10598 bstr = SPEC_BSTR(etype);
10601 lbstr = SPEC_BSTR( letype );
10604 if((blen == 1) && (bstr < 8)) {
10605 /* it is a single bit, so use the appropriate bit instructions */
10606 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10608 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10610 // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10611 if(!IS_PTR(operandType(left))/* && OP_SYMBOL(left)->remat && (ptype == POINTER)*/) {
10612 /* workaround to reduce the extra lfsr instruction */
10613 pic16_emitpcode(POC_BTFSC,
10614 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10616 pic16_loadFSR0 (left, 0);
10617 pic16_emitpcode(POC_BTFSC,
10618 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10621 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10623 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10629 /* the following call to pic16_loadFSR0 is temporary until
10630 * optimization to handle single bit assignments is added
10631 * to the function. Until then use the old safe way! -- VR */
10633 if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
10634 // access symbol directly
10635 pic16_mov2w (AOP(left), 0);
10637 pic16_derefPtr (left, ptype, 0, NULL);
10640 /* if we have bitdisplacement then it fits */
10641 /* into this byte completely or if length is */
10642 /* less than a byte */
10643 if ((shCnt = SPEC_BSTR(etype)) ||
10644 (SPEC_BLEN(etype) <= 8)) {
10646 /* shift right acc */
10649 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10650 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10652 /* VR -- normally I would use the following, but since we use the hack,
10653 * to avoid the masking from AccRsh, why not mask it right now? */
10656 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10659 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10665 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10666 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10673 static void genDataPointerGet(operand *left,
10677 int size, offset = 0, leoffset=0 ;
10679 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10680 pic16_aopOp(result, ic, TRUE);
10684 size = AOP_SIZE(result);
10685 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10689 /* The following tests may save a redudant movff instruction when
10690 * accessing unions */
10692 /* if they are the same */
10693 if (operandsEqu (left, result)) {
10694 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10700 /* if they are the same registers */
10701 if (pic16_sameRegs(AOP(left),AOP(result))) {
10702 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10708 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10709 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10710 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10717 if ( AOP_TYPE(left) == AOP_PCODE) {
10718 fprintf(stderr,"genDataPointerGet %s, %d\n",
10719 AOP(left)->aopu.pcop->name,
10720 (AOP(left)->aopu.pcop->type == PO_DIR)?
10721 PCOR(AOP(left)->aopu.pcop)->instance:
10722 PCOI(AOP(left)->aopu.pcop)->offset);
10726 if(AOP(left)->aopu.pcop->type == PO_DIR)
10727 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10729 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10732 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10734 // pic16_DumpOp("(result)",result);
10735 if(is_LitAOp(AOP(result))) {
10736 pic16_mov2w(AOP(left), offset); // patch 8
10737 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10739 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10740 pic16_popGet(AOP(left), offset), //patch 8
10741 pic16_popGet(AOP(result), offset)));
10749 pic16_freeAsmop(result,NULL,ic,TRUE);
10754 /*-----------------------------------------------------------------*/
10755 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10756 /*-----------------------------------------------------------------*/
10757 static void genNearPointerGet (operand *left,
10761 // asmop *aop = NULL;
10762 //regs *preg = NULL ;
10763 sym_link *rtype, *retype;
10764 sym_link *ltype, *letype;
10768 rtype = operandType(result);
10769 retype= getSpec(rtype);
10770 ltype = operandType(left);
10771 letype= getSpec(ltype);
10773 pic16_aopOp(left,ic,FALSE);
10775 // pic16_DumpOp("(left)",left);
10776 // pic16_DumpOp("(result)",result);
10778 /* if left is rematerialisable and
10779 * result is not bit variable type and
10780 * the left is pointer to data space i.e
10781 * lower 128 bytes of space */
10783 if (AOP_TYPE(left) == AOP_PCODE
10784 && !IS_BITFIELD(retype)
10785 && DCL_TYPE(ltype) == POINTER) {
10787 genDataPointerGet (left,result,ic);
10788 pic16_freeAsmop(left, NULL, ic, TRUE);
10792 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10793 pic16_aopOp (result,ic,TRUE);
10795 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10798 if(IS_BITFIELD( retype )
10799 && (SPEC_BLEN(operandType(result))==1)
10803 int bitstrt, bytestrt;
10805 /* if this is bitfield of size 1, see if we are checking the value
10806 * of a single bit in an if-statement,
10807 * if yes, then don't generate usual code, but execute the
10808 * genIfx directly -- VR */
10812 /* CHECK: if next iCode is IFX
10813 * and current result operand is nextic's conditional operand
10814 * and current result operand live ranges ends at nextic's key number
10816 if((nextic->op == IFX)
10817 && (result == IC_COND(nextic))
10818 && (OP_LIVETO(result) == nextic->seq)
10819 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10821 /* everything is ok then */
10822 /* find a way to optimize the genIfx iCode */
10824 bytestrt = SPEC_BSTR(operandType(result))/8;
10825 bitstrt = SPEC_BSTR(operandType(result))%8;
10827 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10829 genIfxpCOpJump(nextic, jop);
10831 pic16_freeAsmop(left, NULL, ic, TRUE);
10832 pic16_freeAsmop(result, NULL, ic, TRUE);
10838 /* if bitfield then unpack the bits */
10839 if (IS_BITFIELD(letype))
10840 genUnpackBits (result, left, NULL, POINTER);
10842 /* we have can just get the values */
10843 int size = AOP_SIZE(result);
10846 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10848 pic16_loadFSR0( left, 0 );
10852 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10853 pic16_popGet(AOP(result), offset++)));
10855 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10856 pic16_popGet(AOP(result), offset++)));
10862 /* now some housekeeping stuff */
10864 /* we had to allocate for this iCode */
10865 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10866 pic16_freeAsmop(NULL,aop,ic,TRUE);
10868 /* we did not allocate which means left
10869 * already in a pointer register, then
10870 * if size > 0 && this could be used again
10871 * we have to point it back to where it
10873 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10874 if (AOP_SIZE(result) > 1
10875 && !OP_SYMBOL(left)->remat
10876 && ( OP_SYMBOL(left)->liveTo > ic->seq
10878 // int size = AOP_SIZE(result) - 1;
10880 // pic16_emitcode("dec","%s",rname);
10886 pic16_freeAsmop(left,NULL,ic,TRUE);
10887 pic16_freeAsmop(result,NULL,ic,TRUE);
10890 /*-----------------------------------------------------------------*/
10891 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10892 /*-----------------------------------------------------------------*/
10893 static void genPagedPointerGet (operand *left,
10898 regs *preg = NULL ;
10900 sym_link *rtype, *retype;
10902 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10904 rtype = operandType(result);
10905 retype= getSpec(rtype);
10907 pic16_aopOp(left,ic,FALSE);
10909 /* if the value is already in a pointer register
10910 then don't need anything more */
10911 if (!AOP_INPREG(AOP(left))) {
10912 /* otherwise get a free pointer register */
10914 preg = getFreePtr(ic,&aop,FALSE);
10915 pic16_emitcode("mov","%s,%s",
10917 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10918 rname = preg->name ;
10920 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10922 pic16_freeAsmop(left,NULL,ic,TRUE);
10923 pic16_aopOp (result,ic,TRUE);
10925 /* if bitfield then unpack the bits */
10926 if (IS_BITFIELD(retype))
10927 genUnpackBits (result,left,rname,PPOINTER);
10929 /* we have can just get the values */
10930 int size = AOP_SIZE(result);
10935 pic16_emitcode("movx","a,@%s",rname);
10936 pic16_aopPut(AOP(result),"a",offset);
10941 pic16_emitcode("inc","%s",rname);
10945 /* now some housekeeping stuff */
10947 /* we had to allocate for this iCode */
10948 pic16_freeAsmop(NULL,aop,ic,TRUE);
10950 /* we did not allocate which means left
10951 already in a pointer register, then
10952 if size > 0 && this could be used again
10953 we have to point it back to where it
10955 if (AOP_SIZE(result) > 1 &&
10956 !OP_SYMBOL(left)->remat &&
10957 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10959 int size = AOP_SIZE(result) - 1;
10961 pic16_emitcode("dec","%s",rname);
10966 pic16_freeAsmop(result,NULL,ic,TRUE);
10971 /*-----------------------------------------------------------------*/
10972 /* genFarPointerGet - gget value from far space */
10973 /*-----------------------------------------------------------------*/
10974 static void genFarPointerGet (operand *left,
10975 operand *result, iCode *ic)
10978 sym_link *retype = getSpec(operandType(result));
10980 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10982 pic16_aopOp(left,ic,FALSE);
10984 /* if the operand is already in dptr
10985 then we do nothing else we move the value to dptr */
10986 if (AOP_TYPE(left) != AOP_STR) {
10987 /* if this is remateriazable */
10988 if (AOP_TYPE(left) == AOP_IMMD)
10989 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10990 else { /* we need to get it byte by byte */
10991 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10992 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10993 if (options.model == MODEL_FLAT24)
10995 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10999 /* so dptr know contains the address */
11000 pic16_freeAsmop(left,NULL,ic,TRUE);
11001 pic16_aopOp(result,ic,TRUE);
11003 /* if bit then unpack */
11004 if (IS_BITFIELD(retype))
11005 genUnpackBits(result,left,"dptr",FPOINTER);
11007 size = AOP_SIZE(result);
11011 pic16_emitcode("movx","a,@dptr");
11012 pic16_aopPut(AOP(result),"a",offset++);
11014 pic16_emitcode("inc","dptr");
11018 pic16_freeAsmop(result,NULL,ic,TRUE);
11022 /*-----------------------------------------------------------------*/
11023 /* genCodePointerGet - get value from code space */
11024 /*-----------------------------------------------------------------*/
11025 static void genCodePointerGet (operand *left,
11026 operand *result, iCode *ic)
11029 sym_link *retype = getSpec(operandType(result));
11031 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11033 pic16_aopOp(left,ic,FALSE);
11035 /* if the operand is already in dptr
11036 then we do nothing else we move the value to dptr */
11037 if (AOP_TYPE(left) != AOP_STR) {
11038 /* if this is remateriazable */
11039 if (AOP_TYPE(left) == AOP_IMMD)
11040 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11041 else { /* we need to get it byte by byte */
11042 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11043 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11044 if (options.model == MODEL_FLAT24)
11046 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11050 /* so dptr know contains the address */
11051 pic16_freeAsmop(left,NULL,ic,TRUE);
11052 pic16_aopOp(result,ic,FALSE);
11054 /* if bit then unpack */
11055 if (IS_BITFIELD(retype))
11056 genUnpackBits(result,left,"dptr",CPOINTER);
11058 size = AOP_SIZE(result);
11062 pic16_emitcode("clr","a");
11063 pic16_emitcode("movc","a,@a+dptr");
11064 pic16_aopPut(AOP(result),"a",offset++);
11066 pic16_emitcode("inc","dptr");
11070 pic16_freeAsmop(result,NULL,ic,TRUE);
11075 /*-----------------------------------------------------------------*/
11076 /* genGenPointerGet - gget value from generic pointer space */
11077 /*-----------------------------------------------------------------*/
11078 static void genGenPointerGet (operand *left,
11079 operand *result, iCode *ic)
11081 int size, offset, lit;
11082 sym_link *retype = getSpec(operandType(result));
11084 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11085 pic16_aopOp(left,ic,FALSE);
11086 pic16_aopOp(result,ic,FALSE);
11087 size = AOP_SIZE(result);
11089 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11091 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11093 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11094 // load FSR0 from immediate
11095 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11097 // pic16_loadFSR0( left );
11102 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11104 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11111 else { /* we need to get it byte by byte */
11112 // set up FSR0 with address from left
11113 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11114 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11120 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11122 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11129 /* if bit then unpack */
11130 if (IS_BITFIELD(retype))
11131 genUnpackBits(result,left,"BAD",GPOINTER);
11134 pic16_freeAsmop(left,NULL,ic,TRUE);
11135 pic16_freeAsmop(result,NULL,ic,TRUE);
11141 /*-----------------------------------------------------------------*/
11142 /* genGenPointerGet - gget value from generic pointer space */
11143 /*-----------------------------------------------------------------*/
11144 static void genGenPointerGet (operand *left,
11145 operand *result, iCode *ic)
11147 int size, offset, lit;
11148 sym_link *letype = getSpec(operandType(left));
11150 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11151 pic16_aopOp(left,ic,FALSE);
11152 pic16_aopOp(result,ic,TRUE);
11153 size = AOP_SIZE(result);
11155 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11157 /* if bit then unpack */
11158 if (IS_BITFIELD(letype)) {
11159 genUnpackBits(result,left,"BAD",GPOINTER);
11163 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11165 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11166 // load FSR0 from immediate
11167 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11169 werror(W_POSSBUG2, __FILE__, __LINE__);
11174 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11176 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11183 } else { /* we need to get it byte by byte */
11185 /* set up WREG:PRODL:FSR0L with address from left */
11186 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11187 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11188 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11190 pic16_callGenericPointerRW(0, size);
11192 assignResultValue(result, 1);
11198 pic16_freeAsmop(left,NULL,ic,TRUE);
11199 pic16_freeAsmop(result,NULL,ic,TRUE);
11202 /*-----------------------------------------------------------------*/
11203 /* genConstPointerGet - get value from const generic pointer space */
11204 /*-----------------------------------------------------------------*/
11205 static void genConstPointerGet (operand *left,
11206 operand *result, iCode *ic)
11208 //sym_link *retype = getSpec(operandType(result));
11209 // symbol *albl = newiTempLabel(NULL); // patch 15
11210 // symbol *blbl = newiTempLabel(NULL); //
11211 // PIC_OPCODE poc; // patch 15
11215 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11216 pic16_aopOp(left,ic,FALSE);
11217 pic16_aopOp(result,ic,TRUE);
11218 size = AOP_SIZE(result);
11220 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11222 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11224 // set up table pointer
11225 if( (AOP_TYPE(left) == AOP_PCODE)
11226 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11227 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11229 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11230 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11231 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11232 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11233 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11234 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11236 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11237 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11238 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11242 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11243 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11247 pic16_freeAsmop(left,NULL,ic,TRUE);
11248 pic16_freeAsmop(result,NULL,ic,TRUE);
11252 /*-----------------------------------------------------------------*/
11253 /* genPointerGet - generate code for pointer get */
11254 /*-----------------------------------------------------------------*/
11255 static void genPointerGet (iCode *ic)
11257 operand *left, *result ;
11258 sym_link *type, *etype;
11263 left = IC_LEFT(ic);
11264 result = IC_RESULT(ic) ;
11266 /* depending on the type of pointer we need to
11267 move it to the correct pointer register */
11268 type = operandType(left);
11269 etype = getSpec(type);
11272 if (IS_PTR_CONST(type))
11274 if (IS_CODEPTR(type))
11276 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11278 /* if left is of type of pointer then it is simple */
11279 if (IS_PTR(type) && !IS_FUNC(type->next))
11280 p_type = DCL_TYPE(type);
11282 /* we have to go by the storage class */
11283 p_type = PTR_TYPE(SPEC_OCLS(etype));
11285 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11287 if (SPEC_OCLS(etype)->codesp ) {
11288 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11289 //p_type = CPOINTER ;
11291 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11292 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11293 /*p_type = FPOINTER ;*/
11295 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11296 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11297 /* p_type = PPOINTER; */
11299 if (SPEC_OCLS(etype) == idata ) {
11300 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11301 /* p_type = IPOINTER; */
11303 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11304 /* p_type = POINTER ; */
11308 /* now that we have the pointer type we assign
11309 the pointer values */
11313 genNearPointerGet (left,result,ic);
11317 genPagedPointerGet(left,result,ic);
11321 genFarPointerGet (left,result,ic);
11325 genConstPointerGet (left,result,ic);
11326 //pic16_emitcodePointerGet (left,result,ic);
11331 if (IS_PTR_CONST(type))
11332 genConstPointerGet (left,result,ic);
11335 genGenPointerGet (left,result,ic);
11339 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11340 "genPointerGet: illegal pointer type");
11345 /*-----------------------------------------------------------------*/
11346 /* genPackBits - generates code for packed bit storage */
11347 /*-----------------------------------------------------------------*/
11348 static void genPackBits (sym_link *etype , operand *result,
11350 char *rname, int p_type)
11358 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11359 blen = SPEC_BLEN(etype);
11360 bstr = SPEC_BSTR(etype);
11362 retype = getSpec(operandType(right));
11364 if(AOP_TYPE(right) == AOP_LIT) {
11365 if((blen == 1) && (bstr < 8)) {
11367 /* it is a single bit, so use the appropriate bit instructions */
11369 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11371 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11372 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11373 if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11374 /* workaround to reduce the extra lfsr instruction */
11376 pic16_emitpcode(POC_BSF,
11377 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11379 pic16_emitpcode(POC_BCF,
11380 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11383 pic16_loadFSR0(result, 0);
11385 pic16_emitpcode(POC_BSF,
11386 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11388 pic16_emitpcode(POC_BCF,
11389 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11395 /* move literal to W */
11396 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11399 if(IS_BITFIELD(retype)
11400 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11404 rblen = SPEC_BLEN( retype );
11405 rbstr = SPEC_BSTR( retype );
11408 if(IS_BITFIELD(etype)) {
11409 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11410 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11412 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11415 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11417 if(IS_BITFIELD(etype)) {
11418 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11420 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11423 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11427 /* move right to W */
11428 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11431 /* if the bit length is less than or */
11432 /* it exactly fits a byte then */
11433 if((shCnt=SPEC_BSTR(etype))
11434 || SPEC_BLEN(etype) <= 8 ) {
11435 int fsr0_setup = 0;
11437 if (blen != 8 || bstr != 0) {
11438 // we need to combine the value with the old value
11439 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11441 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11442 SPEC_BSTR(etype), SPEC_BLEN(etype));
11444 /* shift left acc */
11447 /* using PRODH as a temporary register here */
11448 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11450 if (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) {
11451 /* access symbol directly */
11452 pic16_mov2w (AOP(result), 0);
11454 /* get old value */
11455 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11458 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11459 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11460 (unsigned char)(0xff >> (8-bstr))) ));
11461 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11462 } // if (blen != 8 || bstr != 0)
11464 /* write new value back */
11465 if (IS_SYMOP(result) & !IS_PTR(operandType(result))) {
11466 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11468 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11477 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11478 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11483 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11484 rLen = SPEC_BLEN(etype)-8;
11486 /* now generate for lengths greater than one byte */
11490 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11496 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11502 pic16_emitcode("movx","@dptr,a");
11507 DEBUGpic16_emitcode(";lcall","__gptrput");
11515 pic16_mov2w(AOP(right), offset++);
11518 /* last last was not complete */
11520 /* save the byte & read byte */
11523 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11524 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11529 pic16_emitcode ("mov","b,a");
11530 pic16_emitcode("movx","a,@dptr");
11534 pic16_emitcode ("push","b");
11535 pic16_emitcode ("push","acc");
11536 pic16_emitcode ("lcall","__gptrget");
11537 pic16_emitcode ("pop","b");
11543 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11544 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11545 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11546 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11547 // pic16_emitcode ("orl","a,b");
11550 // if (p_type == GPOINTER)
11551 // pic16_emitcode("pop","b");
11556 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11557 // pic16_emitcode("mov","@%s,a",rname);
11561 pic16_emitcode("movx","@dptr,a");
11565 DEBUGpic16_emitcode(";lcall","__gptrput");
11572 // pic16_freeAsmop(right, NULL, ic, TRUE);
11574 /*-----------------------------------------------------------------*/
11575 /* genDataPointerSet - remat pointer to data space */
11576 /*-----------------------------------------------------------------*/
11577 static void genDataPointerSet(operand *right,
11581 int size, offset = 0, resoffset=0 ;
11583 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11584 pic16_aopOp(right,ic,FALSE);
11586 size = AOP_SIZE(right);
11588 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11591 if ( AOP_TYPE(result) == AOP_PCODE) {
11592 fprintf(stderr,"genDataPointerSet %s, %d\n",
11593 AOP(result)->aopu.pcop->name,
11594 (AOP(result)->aopu.pcop->type == PO_DIR)?
11595 PCOR(AOP(result)->aopu.pcop)->instance:
11596 PCOI(AOP(result)->aopu.pcop)->offset);
11600 if(AOP(result)->aopu.pcop->type == PO_DIR)
11601 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11604 if (AOP_TYPE(right) == AOP_LIT) {
11607 if(!IS_FLOAT(operandType( right )))
11608 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11611 unsigned long lit_int;
11615 /* take care if literal is a float */
11616 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11617 lit = info.lit_int;
11620 lit = lit >> (8*offset);
11622 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11623 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11625 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11628 pic16_mov2w(AOP(right), offset);
11629 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11635 pic16_freeAsmop(right,NULL,ic,TRUE);
11640 /*-----------------------------------------------------------------*/
11641 /* genNearPointerSet - pic16_emitcode for near pointer put */
11642 /*-----------------------------------------------------------------*/
11643 static void genNearPointerSet (operand *right,
11649 sym_link *ptype = operandType(result);
11650 sym_link *resetype;
11652 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11653 retype= getSpec(operandType(right));
11654 resetype = getSpec(operandType(result));
11656 pic16_aopOp(result,ic,FALSE);
11658 /* if the result is rematerializable &
11659 * in data space & not a bit variable */
11661 /* and result is not a bit variable */
11662 if (AOP_TYPE(result) == AOP_PCODE
11663 // && AOP_TYPE(result) == AOP_IMMD
11664 && DCL_TYPE(ptype) == POINTER
11665 && !IS_BITFIELD(retype)
11666 && !IS_BITFIELD(resetype)) {
11668 genDataPointerSet (right,result,ic);
11669 pic16_freeAsmop(result,NULL,ic,TRUE);
11673 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11674 pic16_aopOp(right,ic,FALSE);
11675 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11677 /* if bitfield then unpack the bits */
11678 if (IS_BITFIELD(resetype)) {
11679 genPackBits (resetype, result, right, NULL, POINTER);
11681 /* we have can just get the values */
11682 int size = AOP_SIZE(right);
11685 pic16_loadFSR0(result, 0);
11687 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11689 if (AOP_TYPE(right) == AOP_LIT) {
11690 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11692 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11694 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11696 } else { // no literal
11698 pic16_emitpcode(POC_MOVFF,
11699 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11700 pic16_popCopyReg(&pic16_pc_postinc0)));
11702 pic16_emitpcode(POC_MOVFF,
11703 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11704 pic16_popCopyReg(&pic16_pc_indf0)));
11711 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11712 /* now some housekeeping stuff */
11714 /* we had to allocate for this iCode */
11715 pic16_freeAsmop(NULL,aop,ic,TRUE);
11717 /* we did not allocate which means left
11718 * already in a pointer register, then
11719 * if size > 0 && this could be used again
11720 * we have to point it back to where it
11722 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11723 if (AOP_SIZE(right) > 1
11724 && !OP_SYMBOL(result)->remat
11725 && ( OP_SYMBOL(result)->liveTo > ic->seq
11728 int size = AOP_SIZE(right) - 1;
11731 pic16_emitcode("decf","fsr0,f");
11732 //pic16_emitcode("dec","%s",rname);
11736 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11739 pic16_freeAsmop(right,NULL,ic,TRUE);
11740 pic16_freeAsmop(result,NULL,ic,TRUE);
11743 /*-----------------------------------------------------------------*/
11744 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11745 /*-----------------------------------------------------------------*/
11746 static void genPagedPointerSet (operand *right,
11751 regs *preg = NULL ;
11755 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11757 retype= getSpec(operandType(right));
11759 pic16_aopOp(result,ic,FALSE);
11761 /* if the value is already in a pointer register
11762 then don't need anything more */
11763 if (!AOP_INPREG(AOP(result))) {
11764 /* otherwise get a free pointer register */
11766 preg = getFreePtr(ic,&aop,FALSE);
11767 pic16_emitcode("mov","%s,%s",
11769 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11770 rname = preg->name ;
11772 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11774 pic16_freeAsmop(result,NULL,ic,TRUE);
11775 pic16_aopOp (right,ic,FALSE);
11777 /* if bitfield then unpack the bits */
11778 if (IS_BITFIELD(retype))
11779 genPackBits (retype,result,right,rname,PPOINTER);
11781 /* we have can just get the values */
11782 int size = AOP_SIZE(right);
11786 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11789 pic16_emitcode("movx","@%s,a",rname);
11792 pic16_emitcode("inc","%s",rname);
11798 /* now some housekeeping stuff */
11800 /* we had to allocate for this iCode */
11801 pic16_freeAsmop(NULL,aop,ic,TRUE);
11803 /* we did not allocate which means left
11804 already in a pointer register, then
11805 if size > 0 && this could be used again
11806 we have to point it back to where it
11808 if (AOP_SIZE(right) > 1 &&
11809 !OP_SYMBOL(result)->remat &&
11810 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11812 int size = AOP_SIZE(right) - 1;
11814 pic16_emitcode("dec","%s",rname);
11819 pic16_freeAsmop(right,NULL,ic,TRUE);
11824 /*-----------------------------------------------------------------*/
11825 /* genFarPointerSet - set value from far space */
11826 /*-----------------------------------------------------------------*/
11827 static void genFarPointerSet (operand *right,
11828 operand *result, iCode *ic)
11831 sym_link *retype = getSpec(operandType(right));
11833 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11834 pic16_aopOp(result,ic,FALSE);
11836 /* if the operand is already in dptr
11837 then we do nothing else we move the value to dptr */
11838 if (AOP_TYPE(result) != AOP_STR) {
11839 /* if this is remateriazable */
11840 if (AOP_TYPE(result) == AOP_IMMD)
11841 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11842 else { /* we need to get it byte by byte */
11843 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11844 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11845 if (options.model == MODEL_FLAT24)
11847 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11851 /* so dptr know contains the address */
11852 pic16_freeAsmop(result,NULL,ic,TRUE);
11853 pic16_aopOp(right,ic,FALSE);
11855 /* if bit then unpack */
11856 if (IS_BITFIELD(retype))
11857 genPackBits(retype,result,right,"dptr",FPOINTER);
11859 size = AOP_SIZE(right);
11863 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11865 pic16_emitcode("movx","@dptr,a");
11867 pic16_emitcode("inc","dptr");
11871 pic16_freeAsmop(right,NULL,ic,TRUE);
11874 /*-----------------------------------------------------------------*/
11875 /* genGenPointerSet - set value from generic pointer space */
11876 /*-----------------------------------------------------------------*/
11878 static void genGenPointerSet (operand *right,
11879 operand *result, iCode *ic)
11881 int i, size, offset, lit;
11882 sym_link *retype = getSpec(operandType(right));
11884 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11886 pic16_aopOp(result,ic,FALSE);
11887 pic16_aopOp(right,ic,FALSE);
11888 size = AOP_SIZE(right);
11891 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11893 /* if the operand is already in dptr
11894 then we do nothing else we move the value to dptr */
11895 if (AOP_TYPE(result) != AOP_STR) {
11896 /* if this is remateriazable */
11897 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11898 // WARNING: anythig until "else" is untested!
11899 if (AOP_TYPE(result) == AOP_IMMD) {
11900 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11901 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11902 // load FSR0 from immediate
11903 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11907 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11909 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11915 else { /* we need to get it byte by byte */
11916 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11917 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11919 // set up FSR0 with address of result
11920 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11921 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11923 /* hack hack! see if this the FSR. If so don't load W */
11924 if(AOP_TYPE(right) != AOP_ACC) {
11926 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11928 if(AOP_TYPE(right) == AOP_LIT)
11931 // note: pic16_popGet handles sign extension
11932 for(i=0;i<size;i++) {
11933 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11935 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11937 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11942 for(i=0;i<size;i++) {
11944 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11945 pic16_popCopyReg(&pic16_pc_postinc0)));
11947 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11948 pic16_popCopyReg(&pic16_pc_indf0)));
11954 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11955 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11957 } // if (AOP_TYPE(result) != AOP_IMMD)
11959 } // if (AOP_TYPE(result) != AOP_STR)
11960 /* so dptr know contains the address */
11963 /* if bit then unpack */
11964 if (IS_BITFIELD(retype))
11965 genPackBits(retype,result,right,"dptr",GPOINTER);
11967 size = AOP_SIZE(right);
11970 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11972 // set up FSR0 with address of result
11973 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11974 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11977 if (AOP_TYPE(right) == AOP_LIT) {
11978 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11980 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11982 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11984 } else { // no literal
11986 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11988 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11996 pic16_freeAsmop(right,NULL,ic,TRUE);
11997 pic16_freeAsmop(result,NULL,ic,TRUE);
12001 static void genGenPointerSet (operand *right,
12002 operand *result, iCode *ic)
12005 sym_link *retype = getSpec(operandType(result));
12007 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12009 pic16_aopOp(result,ic,FALSE);
12010 pic16_aopOp(right,ic,FALSE);
12011 size = AOP_SIZE(right);
12013 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12016 /* if bit then unpack */
12017 if (IS_BITFIELD(retype)) {
12018 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12019 genPackBits(retype,result,right,"dptr",GPOINTER);
12023 size = AOP_SIZE(right);
12025 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12028 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12030 /* value of right+0 is placed on stack, which will be retrieved
12031 * by the support function this restoring the stack. The important
12032 * thing is that there is no need to manually restore stack pointer
12034 pushaop(AOP(right), 0);
12035 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12036 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12037 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12038 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12040 /* load address to write to in WREG:FSR0H:FSR0L */
12041 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12042 pic16_popCopyReg(&pic16_pc_fsr0l)));
12043 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12044 pic16_popCopyReg(&pic16_pc_prodl)));
12045 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12047 pic16_callGenericPointerRW(1, size);
12050 pic16_freeAsmop(right,NULL,ic,TRUE);
12051 pic16_freeAsmop(result,NULL,ic,TRUE);
12054 /*-----------------------------------------------------------------*/
12055 /* genPointerSet - stores the value into a pointer location */
12056 /*-----------------------------------------------------------------*/
12057 static void genPointerSet (iCode *ic)
12059 operand *right, *result ;
12060 sym_link *type, *etype;
12065 right = IC_RIGHT(ic);
12066 result = IC_RESULT(ic) ;
12068 /* depending on the type of pointer we need to
12069 move it to the correct pointer register */
12070 type = operandType(result);
12071 etype = getSpec(type);
12073 /* if left is of type of pointer then it is simple */
12074 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12075 p_type = DCL_TYPE(type);
12078 /* we have to go by the storage class */
12079 p_type = PTR_TYPE(SPEC_OCLS(etype));
12081 /* if (SPEC_OCLS(etype)->codesp ) { */
12082 /* p_type = CPOINTER ; */
12085 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12086 /* p_type = FPOINTER ; */
12088 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12089 /* p_type = PPOINTER ; */
12091 /* if (SPEC_OCLS(etype) == idata ) */
12092 /* p_type = IPOINTER ; */
12094 /* p_type = POINTER ; */
12097 /* now that we have the pointer type we assign
12098 the pointer values */
12102 genNearPointerSet (right,result,ic);
12106 genPagedPointerSet (right,result,ic);
12110 genFarPointerSet (right,result,ic);
12114 genGenPointerSet (right,result,ic);
12118 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12119 "genPointerSet: illegal pointer type");
12123 /*-----------------------------------------------------------------*/
12124 /* genIfx - generate code for Ifx statement */
12125 /*-----------------------------------------------------------------*/
12126 static void genIfx (iCode *ic, iCode *popIc)
12128 operand *cond = IC_COND(ic);
12133 pic16_aopOp(cond,ic,FALSE);
12135 /* get the value into acc */
12136 if (AOP_TYPE(cond) != AOP_CRY)
12137 pic16_toBoolean(cond);
12140 /* the result is now in the accumulator */
12141 pic16_freeAsmop(cond,NULL,ic,TRUE);
12143 /* if there was something to be popped then do it */
12147 /* if the condition is a bit variable */
12148 if (isbit && IS_ITEMP(cond) &&
12150 genIfxJump(ic,"c");
12151 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12153 if (isbit && !IS_ITEMP(cond))
12154 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12156 genIfxJump(ic,"a");
12161 /*-----------------------------------------------------------------*/
12162 /* genAddrOf - generates code for address of */
12163 /*-----------------------------------------------------------------*/
12164 static void genAddrOf (iCode *ic)
12166 operand *result, *left;
12168 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12169 pCodeOp *pcop0, *pcop1, *pcop2;
12173 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12175 sym = OP_SYMBOL( IC_LEFT(ic) );
12178 /* get address of symbol on stack */
12179 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12181 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12182 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12185 // operands on stack are accessible via "FSR2 + index" with index
12186 // starting at 2 for arguments and growing from 0 downwards for
12187 // local variables (index == 0 is not assigned so we add one here)
12189 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12191 assert (soffs < 0);
12194 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12195 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12196 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12197 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12198 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12199 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12200 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12206 // if(pic16_debug_verbose) {
12207 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12208 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12211 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12212 size = AOP_SIZE(IC_RESULT(ic));
12214 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12215 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12216 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12219 pic16_emitpcode(POC_MOVLW, pcop0);
12220 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12221 pic16_emitpcode(POC_MOVLW, pcop1);
12222 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12223 pic16_emitpcode(POC_MOVLW, pcop2);
12224 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12227 pic16_emitpcode(POC_MOVLW, pcop0);
12228 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12229 pic16_emitpcode(POC_MOVLW, pcop1);
12230 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12232 pic16_emitpcode(POC_MOVLW, pcop0);
12233 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12236 pic16_freeAsmop(left, NULL, ic, FALSE);
12238 pic16_freeAsmop(result,NULL,ic,TRUE);
12243 /*-----------------------------------------------------------------*/
12244 /* genFarFarAssign - assignment when both are in far space */
12245 /*-----------------------------------------------------------------*/
12246 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12248 int size = AOP_SIZE(right);
12251 /* first push the right side on to the stack */
12253 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12255 pic16_emitcode ("push","acc");
12258 pic16_freeAsmop(right,NULL,ic,FALSE);
12259 /* now assign DPTR to result */
12260 pic16_aopOp(result,ic,FALSE);
12261 size = AOP_SIZE(result);
12263 pic16_emitcode ("pop","acc");
12264 pic16_aopPut(AOP(result),"a",--offset);
12266 pic16_freeAsmop(result,NULL,ic,FALSE);
12271 /*-----------------------------------------------------------------*/
12272 /* genAssign - generate code for assignment */
12273 /*-----------------------------------------------------------------*/
12274 static void genAssign (iCode *ic)
12276 operand *result, *right;
12277 int size, offset,know_W;
12278 unsigned long lit = 0L;
12280 result = IC_RESULT(ic);
12281 right = IC_RIGHT(ic) ;
12285 /* if they are the same */
12286 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12289 /* reversed order operands are aopOp'ed so that result operand
12290 * is effective in case right is a stack symbol. This maneauver
12291 * allows to use the _G.resDirect flag later */
12292 pic16_aopOp(result,ic,TRUE);
12293 pic16_aopOp(right,ic,FALSE);
12295 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12297 /* if they are the same registers */
12298 if (pic16_sameRegs(AOP(right),AOP(result)))
12301 /* if the result is a bit */
12302 if (AOP_TYPE(result) == AOP_CRY) {
12303 /* if the right size is a literal then
12304 we know what the value is */
12305 if (AOP_TYPE(right) == AOP_LIT) {
12307 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12308 pic16_popGet(AOP(result),0));
12310 if (((int) operandLitValue(right)))
12311 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12312 AOP(result)->aopu.aop_dir,
12313 AOP(result)->aopu.aop_dir);
12315 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12316 AOP(result)->aopu.aop_dir,
12317 AOP(result)->aopu.aop_dir);
12321 /* the right is also a bit variable */
12322 if (AOP_TYPE(right) == AOP_CRY) {
12323 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12324 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12325 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12327 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12328 AOP(result)->aopu.aop_dir,
12329 AOP(result)->aopu.aop_dir);
12330 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12331 AOP(right)->aopu.aop_dir,
12332 AOP(right)->aopu.aop_dir);
12333 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12334 AOP(result)->aopu.aop_dir,
12335 AOP(result)->aopu.aop_dir);
12339 /* we need to or */
12340 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12341 pic16_toBoolean(right);
12343 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12344 //pic16_aopPut(AOP(result),"a",0);
12348 /* bit variables done */
12350 size = AOP_SIZE(result);
12353 if(AOP_TYPE(right) == AOP_LIT) {
12354 if(!IS_FLOAT(operandType( right )))
12355 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12358 unsigned long lit_int;
12362 /* take care if literal is a float */
12363 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12364 lit = info.lit_int;
12368 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12369 // sizeof(unsigned long int), sizeof(float));
12372 if (AOP_TYPE(right) == AOP_REG) {
12373 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12375 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12380 /* when do we have to read the program memory?
12381 * - if right itself is a symbol in code space
12382 * (we don't care what it points to if it's a pointer)
12383 * - AND right is not a function (we would want its address)
12385 if(AOP_TYPE(right) != AOP_LIT
12386 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12387 && !IS_FUNC(OP_SYM_TYPE(right))
12388 && !IS_ITEMP(right))
12390 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12391 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12393 // set up table pointer
12394 if(is_LitOp(right)) {
12395 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12396 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12397 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12398 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12399 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12400 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12401 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12403 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12404 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12405 pic16_popCopyReg(&pic16_pc_tblptrl)));
12406 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12407 pic16_popCopyReg(&pic16_pc_tblptrh)));
12408 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12409 pic16_popCopyReg(&pic16_pc_tblptru)));
12412 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12413 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12415 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12416 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12417 pic16_popGet(AOP(result),offset)));
12421 /* FIXME: for pointers we need to extend differently (according
12422 * to pointer type DATA/CODE/EEPROM/... :*/
12423 size = getSize(OP_SYM_TYPE(right));
12424 if(AOP_SIZE(result) > size) {
12425 size = AOP_SIZE(result) - size;
12427 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12437 /* VR - What is this?! */
12438 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12439 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12440 if(aopIdx(AOP(result),0) == 4) {
12442 /* this is a workaround to save value of right into wreg too,
12443 * value of wreg is going to be used later */
12444 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12445 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12446 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12450 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12456 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12457 if(AOP_TYPE(right) == AOP_LIT) {
12459 if(know_W != (lit&0xff))
12460 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12462 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12464 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12468 } else if (AOP_TYPE(right) == AOP_CRY) {
12469 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12471 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12472 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12473 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12475 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12476 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12477 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12479 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12481 if(!_G.resDirect) /* use this aopForSym feature */
12482 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12489 pic16_freeAsmop (right,NULL,ic,FALSE);
12490 pic16_freeAsmop (result,NULL,ic,TRUE);
12493 /*-----------------------------------------------------------------*/
12494 /* genJumpTab - generates code for jump table */
12495 /*-----------------------------------------------------------------*/
12496 static void genJumpTab (iCode *ic)
12501 pCodeOp *jt_offs_hi;
12506 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12507 /* get the condition into accumulator */
12508 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12510 /* multiply by three */
12511 pic16_emitcode("add","a,acc");
12512 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12514 jtab = newiTempLabel(NULL);
12515 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12516 pic16_emitcode("jmp","@a+dptr");
12517 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12520 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12521 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12523 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12524 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12525 pic16_emitpLabel(jtab->key);
12529 jt_offs = pic16_popGetTempReg(0);
12530 jt_offs_hi = pic16_popGetTempReg(1);
12531 jt_label = pic16_popGetLabel (jtab->key);
12532 //fprintf (stderr, "Creating jump table...\n");
12534 // calculate offset into jump table (idx * sizeof (GOTO))
12535 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12536 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12537 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12538 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12539 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12540 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12541 pic16_emitpcode(POC_MOVWF , jt_offs);
12543 // prepare PCLATx (set to first entry in jump table)
12544 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12545 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12546 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12547 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12548 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12550 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12551 pic16_emitpcode(POC_ADDWF , jt_offs);
12552 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12553 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12555 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12557 // release temporaries and prepare jump into table (new PCL --> WREG)
12558 pic16_emitpcode(POC_MOVFW , jt_offs);
12559 pic16_popReleaseTempReg (jt_offs_hi, 1);
12560 pic16_popReleaseTempReg (jt_offs, 0);
12562 // jump into the table
12563 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12565 pic16_emitpLabelFORCE(jtab->key);
12568 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12569 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12571 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12572 /* now generate the jump labels */
12573 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12574 jtab = setNextItem(IC_JTLABELS(ic))) {
12575 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12576 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12579 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12583 /*-----------------------------------------------------------------*/
12584 /* genMixedOperation - gen code for operators between mixed types */
12585 /*-----------------------------------------------------------------*/
12587 TSD - Written for the PIC port - but this unfortunately is buggy.
12588 This routine is good in that it is able to efficiently promote
12589 types to different (larger) sizes. Unfortunately, the temporary
12590 variables that are optimized out by this routine are sometimes
12591 used in other places. So until I know how to really parse the
12592 iCode tree, I'm going to not be using this routine :(.
12594 static int genMixedOperation (iCode *ic)
12597 operand *result = IC_RESULT(ic);
12598 sym_link *ctype = operandType(IC_LEFT(ic));
12599 operand *right = IC_RIGHT(ic);
12605 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12607 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12613 nextright = IC_RIGHT(nextic);
12614 nextleft = IC_LEFT(nextic);
12615 nextresult = IC_RESULT(nextic);
12617 pic16_aopOp(right,ic,FALSE);
12618 pic16_aopOp(result,ic,FALSE);
12619 pic16_aopOp(nextright, nextic, FALSE);
12620 pic16_aopOp(nextleft, nextic, FALSE);
12621 pic16_aopOp(nextresult, nextic, FALSE);
12623 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12625 operand *t = right;
12629 pic16_emitcode(";remove right +","");
12631 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12633 operand *t = right;
12637 pic16_emitcode(";remove left +","");
12641 big = AOP_SIZE(nextleft);
12642 small = AOP_SIZE(nextright);
12644 switch(nextic->op) {
12647 pic16_emitcode(";optimize a +","");
12648 /* if unsigned or not an integral type */
12649 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12650 pic16_emitcode(";add a bit to something","");
12653 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12655 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12656 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12657 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12659 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12667 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12668 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12669 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12672 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12674 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12675 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12676 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12677 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12678 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12681 pic16_emitcode("rlf","known_zero,w");
12688 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12689 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12690 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12692 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12702 pic16_freeAsmop(right,NULL,ic,TRUE);
12703 pic16_freeAsmop(result,NULL,ic,TRUE);
12704 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12705 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12707 nextic->generated = 1;
12714 /*-----------------------------------------------------------------*/
12715 /* genCast - gen code for casting */
12716 /*-----------------------------------------------------------------*/
12717 static void genCast (iCode *ic)
12719 operand *result = IC_RESULT(ic);
12720 sym_link *ctype = operandType(IC_LEFT(ic));
12721 sym_link *rtype = operandType(IC_RIGHT(ic));
12722 sym_link *restype = operandType(IC_RESULT(ic));
12723 operand *right = IC_RIGHT(ic);
12729 /* if they are equivalent then do nothing */
12730 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12733 pic16_aopOp(result,ic,FALSE);
12734 pic16_aopOp(right,ic,FALSE) ;
12736 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12739 /* if the result is a bit */
12740 if (AOP_TYPE(result) == AOP_CRY) {
12742 /* if the right size is a literal then
12743 * we know what the value is */
12744 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12746 if (AOP_TYPE(right) == AOP_LIT) {
12747 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12748 pic16_popGet(AOP(result),0));
12750 if (((int) operandLitValue(right)))
12751 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12752 AOP(result)->aopu.aop_dir,
12753 AOP(result)->aopu.aop_dir);
12755 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12756 AOP(result)->aopu.aop_dir,
12757 AOP(result)->aopu.aop_dir);
12761 /* the right is also a bit variable */
12762 if (AOP_TYPE(right) == AOP_CRY) {
12764 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12766 pic16_emitcode("clrc","");
12767 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12768 AOP(right)->aopu.aop_dir,
12769 AOP(right)->aopu.aop_dir);
12770 pic16_aopPut(AOP(result),"c",0);
12774 /* we need to or */
12775 if (AOP_TYPE(right) == AOP_REG) {
12776 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12777 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12778 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12780 pic16_toBoolean(right);
12781 pic16_aopPut(AOP(result),"a",0);
12785 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12788 size = AOP_SIZE(result);
12790 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12792 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12793 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12794 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12797 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12802 if(IS_BITFIELD(getSpec(restype))
12803 && IS_BITFIELD(getSpec(rtype))) {
12804 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12807 /* if they are the same size : or less */
12808 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12810 /* if they are in the same place */
12811 if (pic16_sameRegs(AOP(right),AOP(result)))
12814 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12816 if (IS_PTR_CONST(rtype))
12818 if (IS_CODEPTR(rtype))
12820 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12823 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12825 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12827 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12830 if(AOP_TYPE(right) == AOP_IMMD) {
12831 pCodeOp *pcop0, *pcop1, *pcop2;
12832 symbol *sym = OP_SYMBOL( right );
12834 size = AOP_SIZE(result);
12836 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12838 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12840 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12843 pic16_emitpcode(POC_MOVLW, pcop0);
12844 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12845 pic16_emitpcode(POC_MOVLW, pcop1);
12846 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12847 pic16_emitpcode(POC_MOVLW, pcop2);
12848 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12851 pic16_emitpcode(POC_MOVLW, pcop0);
12852 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12853 pic16_emitpcode(POC_MOVLW, pcop1);
12854 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12856 pic16_emitpcode(POC_MOVLW, pcop0);
12857 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12861 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12862 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12863 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12864 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12865 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12866 if(AOP_SIZE(result) <2)
12867 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12869 /* if they in different places then copy */
12870 size = AOP_SIZE(result);
12873 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12874 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12881 /* if the result is of type pointer */
12882 if (IS_PTR(ctype)) {
12884 sym_link *type = operandType(right);
12885 sym_link *etype = getSpec(type);
12887 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12889 /* pointer to generic pointer */
12890 if (IS_GENPTR(ctype)) {
12894 p_type = DCL_TYPE(type);
12896 /* we have to go by the storage class */
12897 p_type = PTR_TYPE(SPEC_OCLS(etype));
12899 /* if (SPEC_OCLS(etype)->codesp ) */
12900 /* p_type = CPOINTER ; */
12902 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12903 /* p_type = FPOINTER ; */
12905 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12906 /* p_type = PPOINTER; */
12908 /* if (SPEC_OCLS(etype) == idata ) */
12909 /* p_type = IPOINTER ; */
12911 /* p_type = POINTER ; */
12914 /* the first two bytes are known */
12915 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
12916 size = GPTRSIZE - 1;
12919 if(offset < AOP_SIZE(right)) {
12920 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12921 pic16_mov2f(AOP(result), AOP(right), offset);
12923 if ((AOP_TYPE(right) == AOP_PCODE) &&
12924 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12925 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12926 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12929 pic16_aopPut(AOP(result),
12930 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12935 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12938 /* the last byte depending on type */
12942 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12943 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12944 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12948 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12952 pic16_emitcode(";BUG!? ","%d",__LINE__);
12956 pic16_emitcode(";BUG!? ","%d",__LINE__);
12961 if (GPTRSIZE > AOP_SIZE(right)) {
12962 // assume data pointer... THIS MIGHT BE WRONG!
12963 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12964 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12966 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12971 /* this should never happen */
12972 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12973 "got unknown pointer type");
12976 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
12982 /* just copy the pointers */
12983 size = AOP_SIZE(result);
12986 pic16_aopPut(AOP(result),
12987 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12996 /* so we now know that the size of destination is greater
12997 than the size of the source.
12998 Now, if the next iCode is an operator then we might be
12999 able to optimize the operation without performing a cast.
13001 if(genMixedOperation(ic))
13004 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13006 /* we move to result for the size of source */
13007 size = AOP_SIZE(right);
13012 pic16_mov2f(AOP(result), AOP(right), offset);
13016 /* now depending on the sign of the destination */
13017 size = AOP_SIZE(result) - AOP_SIZE(right);
13018 /* if unsigned or not an integral type */
13019 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13021 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13023 /* we need to extend the sign :( */
13026 /* Save one instruction of casting char to int */
13027 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13028 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13029 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13031 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13034 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13036 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13038 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13041 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13046 pic16_freeAsmop(right,NULL,ic,TRUE);
13047 pic16_freeAsmop(result,NULL,ic,TRUE);
13051 /*-----------------------------------------------------------------*/
13052 /* genDjnz - generate decrement & jump if not zero instrucion */
13053 /*-----------------------------------------------------------------*/
13054 static int genDjnz (iCode *ic, iCode *ifx)
13056 symbol *lbl, *lbl1;
13057 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13062 /* if the if condition has a false label
13063 then we cannot save */
13067 /* if the minus is not of the form
13069 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13070 !IS_OP_LITERAL(IC_RIGHT(ic)))
13073 if (operandLitValue(IC_RIGHT(ic)) != 1)
13076 /* if the size of this greater than one then no
13078 if (getSize(operandType(IC_RESULT(ic))) > 1)
13081 /* otherwise we can save BIG */
13082 lbl = newiTempLabel(NULL);
13083 lbl1= newiTempLabel(NULL);
13085 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13087 if (IS_AOP_PREG(IC_RESULT(ic))) {
13088 pic16_emitcode("dec","%s",
13089 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13090 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13091 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13095 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13096 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13098 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13099 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13103 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13104 ifx->generated = 1;
13108 /*-----------------------------------------------------------------*/
13109 /* genReceive - generate code for a receive iCode */
13110 /*-----------------------------------------------------------------*/
13111 static void genReceive (iCode *ic)
13117 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13118 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13120 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13122 if (isOperandInFarSpace(IC_RESULT(ic))
13123 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13124 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13126 int size = getSize(operandType(IC_RESULT(ic)));
13127 int offset = pic16_fReturnSizePic - size;
13131 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13132 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13136 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13138 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13139 size = AOP_SIZE(IC_RESULT(ic));
13142 pic16_emitcode ("pop","acc");
13143 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13146 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13148 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13151 /* set pseudo stack pointer to where it should be - dw*/
13152 GpsuedoStkPtr = ic->parmBytes;
13154 /* setting GpsuedoStkPtr has side effects here: */
13155 assignResultValue(IC_RESULT(ic), 0);
13158 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13161 /*-----------------------------------------------------------------*/
13162 /* genDummyRead - generate code for dummy read of volatiles */
13163 /*-----------------------------------------------------------------*/
13165 genDummyRead (iCode * ic)
13171 if (op && IS_SYMOP(op)) {
13172 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13173 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13176 pic16_aopOp (op, ic, FALSE);
13177 for (i=0; i < AOP_SIZE(op); i++) {
13178 // may need to protect this from the peepholer -- this is not nice but works...
13179 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13180 pic16_mov2w (AOP(op),i);
13181 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13183 pic16_freeAsmop (op, NULL, ic, TRUE);
13185 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13189 /*-----------------------------------------------------------------*/
13190 /* genpic16Code - generate code for pic16 based controllers */
13191 /*-----------------------------------------------------------------*/
13193 * At this point, ralloc.c has gone through the iCode and attempted
13194 * to optimize in a way suitable for a PIC. Now we've got to generate
13195 * PIC instructions that correspond to the iCode.
13197 * Once the instructions are generated, we'll pass through both the
13198 * peep hole optimizer and the pCode optimizer.
13199 *-----------------------------------------------------------------*/
13201 void genpic16Code (iCode *lic)
13206 lineHead = lineCurr = NULL;
13208 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13209 pic16_addpBlock(pb);
13212 /* if debug information required */
13213 if (options.debug && currFunc) {
13215 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13220 for (ic = lic ; ic ; ic = ic->next ) {
13222 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13223 if ( cln != ic->lineno ) {
13224 if ( options.debug ) {
13225 debugFile->writeCLine (ic);
13228 if(!options.noCcodeInAsm) {
13229 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13230 printCLine(ic->filename, ic->lineno)));
13236 if(options.iCodeInAsm) {
13239 /* insert here code to print iCode as comment */
13240 l = Safe_strdup(printILine(ic));
13241 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13244 /* if the result is marked as
13245 * spilt and rematerializable or code for
13246 * this has already been generated then
13248 if (resultRemat(ic) || ic->generated )
13251 /* depending on the operation */
13270 /* IPOP happens only when trying to restore a
13271 * spilt live range, if there is an ifx statement
13272 * following this pop then the if statement might
13273 * be using some of the registers being popped which
13274 * would destroy the contents of the register so
13275 * we need to check for this condition and handle it */
13277 && ic->next->op == IFX
13278 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13279 genIfx (ic->next,ic);
13297 genEndFunction (ic);
13313 pic16_genPlus (ic) ;
13317 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13318 pic16_genMinus (ic);
13334 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13338 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13344 /* note these two are xlated by algebraic equivalence
13345 * during parsing SDCC.y */
13346 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13347 "got '>=' or '<=' shouldn't have come here");
13351 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13363 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13367 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13371 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13395 genRightShift (ic);
13398 case GET_VALUE_AT_ADDRESS:
13403 if (POINTER_SET(ic))
13430 addSet(&_G.sendSet,ic);
13433 case DUMMY_READ_VOLATILE:
13443 /* now we are ready to call the
13444 peep hole optimizer */
13445 if (!options.nopeep)
13446 peepHole (&lineHead);
13448 /* now do the actual printing */
13449 printLine (lineHead, codeOutFile);
13452 DFPRINTF((stderr,"printing pBlock\n\n"));
13453 pic16_printpBlock(stdout,pb);