1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic16
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002)
9 - Vangelis Rokas vrokas@otenet.gr (2003,2004,2005)
10 Bug Fixes - Raphael Neider rneider@web.de (2004,2005)
12 This program is free software; you can redistribute it and/or modify it
13 under the terms of the GNU General Public License as published by the
14 Free Software Foundation; either version 2, or (at your option) any
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 In other words, you are welcome to use, share and improve this program.
27 You are forbidden to forbid anyone else to use, share and improve
28 what you give them. Help stamp out software-hoarding!
31 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
32 Made everything static
33 -------------------------------------------------------------------------*/
39 #include "SDCCglobl.h"
43 #include "SDCCpeeph.h"
51 /* Set the following to 1 to enable the slower/bigger
52 * but more robust generic shifting routine (which also
53 * operates correctly with negative shift values). */
54 #define USE_GENERIC_SIGNED_SHIFT 1
56 /* Set the following to 1 to enable the new
57 * stripped down genCmp version.
58 * This version should be easier to understand,
59 * more reliable and (sigh) slighly slower. */
60 #define USE_SIMPLE_GENCMP 1
62 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
64 void pic16_genMult8X8_8 (operand *, operand *,operand *);
65 void pic16_genMult16X16_16(operand *, operand *, operand *);
66 void pic16_genMult32X32_32(operand *, operand *, operand *);
67 pCode *pic16_AssembleLine(char *line, int peeps);
68 extern void pic16_printpBlock(FILE *of, pBlock *pb);
69 static asmop *newAsmop (short type);
70 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
71 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
72 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
73 static pCodeOp *pic16_popRegFromIdx(int rIdx);
75 //static int aopIdx (asmop *aop, int offset);
77 int pic16_labelOffset=0;
78 extern int pic16_debug_verbose;
79 #if !(USE_GENERIC_SIGNED_SHIFT)
80 static int optimized_for_speed = 0;
89 /* max_key keeps track of the largest label number used in
90 a function. This is then used to adjust the label offset
91 for the next function.
94 static int GpsuedoStkPtr=0;
96 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
98 unsigned int pic16aopLiteral (value *val, int offset);
99 const char *pic16_AopType(short type);
100 static iCode *ifxForOp ( operand *op, iCode *ic );
102 void pic16_pushpCodeOp(pCodeOp *pcop);
103 void pic16_poppCodeOp(pCodeOp *pcop);
105 static bool is_LitOp(operand *op);
106 static bool is_LitAOp(asmop *aop);
109 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
111 /* set the following macro to 1 to enable passing the
112 * first byte of functions parameters via WREG */
113 #define USE_WREG_IN_FUNC_PARAMS 0
116 /* this is the down and dirty file with all kinds of
117 kludgy & hacky stuff. This is what it is all about
118 CODE GENERATION for a specific MCU . some of the
119 routines may be reusable, will have to see */
121 static char *zero = "#0x00";
122 static char *one = "#0x01";
123 //static char *spname = "sp";
127 * Function return value policy (MSB-->LSB):
129 * 16 bits -> PRODL:WREG
130 * 24 bits -> PRODH:PRODL:WREG
131 * 32 bits -> FSR0L:PRODH:PRODL:WREG
132 * >32 bits -> on stack, and FSR0 points to the beginning
137 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
138 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
139 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
140 static char **fReturn = fReturnpic16;
142 static char *accUse[] = {"WREG"};
144 //static short rbank = -1;
158 bitVect *fregsUsed; /* registers used in function */
160 set *sregsAllocSet; /* registers used to store stack variables */
161 int stack_lat; /* stack offset latency */
163 int useWreg; /* flag when WREG is used to pass function parameter */
166 extern int pic16_ptrRegReq ;
167 extern int pic16_nRegs;
168 extern FILE *codeOutFile;
169 //static void saverbank (int, iCode *,bool);
171 static lineNode *lineHead = NULL;
172 static lineNode *lineCurr = NULL;
174 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
175 0xE0, 0xC0, 0x80, 0x00};
176 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
177 0x07, 0x03, 0x01, 0x00};
181 /*-----------------------------------------------------------------*/
182 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
183 /* exponent of 2 is returned, otherwise -1 is */
185 /* note that this is similar to the function `powof2' in SDCCsymt */
189 /*-----------------------------------------------------------------*/
190 int pic16_my_powof2 (unsigned long num)
193 if( (num & (num-1)) == 0) {
206 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
208 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
210 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
211 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
212 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
213 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
214 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
215 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
216 ((result) ? AOP_SIZE(result) : 0));
219 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
222 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
224 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
225 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
226 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
227 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
228 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
229 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
233 void pic16_emitpcomment (char *fmt, ...)
236 char lb[INITIAL_INLINEASM];
237 unsigned char *lbp = lb;
242 vsprintf(lb+1,fmt,ap);
244 while (isspace(*lbp)) lbp++;
247 lineCurr = (lineCurr ?
248 connectLine(lineCurr,newLineNode(lb)) :
249 (lineHead = newLineNode(lb)));
250 lineCurr->isInline = _G.inLine;
251 lineCurr->isDebug = _G.debugLine;
253 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
256 // fprintf(stderr, "%s\n", lb);
259 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
262 char lb[INITIAL_INLINEASM];
263 unsigned char *lbp = lb;
265 if(!pic16_debug_verbose)
272 sprintf(lb,"%s\t",inst);
274 sprintf(lb,"%s",inst);
275 vsprintf(lb+(strlen(lb)),fmt,ap);
279 while (isspace(*lbp)) lbp++;
282 lineCurr = (lineCurr ?
283 connectLine(lineCurr,newLineNode(lb)) :
284 (lineHead = newLineNode(lb)));
285 lineCurr->isInline = _G.inLine;
286 lineCurr->isDebug = _G.debugLine;
288 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
291 // fprintf(stderr, "%s\n", lb);
296 void pic16_emitpLabel(int key)
298 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
301 void pic16_emitpLabelFORCE(int key)
303 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
306 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
307 * NEVER call pic16_emitpcode_real directly, please... */
308 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
312 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
314 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
317 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
320 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
322 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
325 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
328 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
334 #define pic16_emitcode DEBUGpic16_emitcode
336 /*-----------------------------------------------------------------*/
337 /* pic16_emitcode - writes the code into a file : for now it is simple */
338 /*-----------------------------------------------------------------*/
339 void pic16_emitcode (char *inst,char *fmt, ...)
342 char lb[INITIAL_INLINEASM];
343 unsigned char *lbp = lb;
349 sprintf(lb,"%s\t",inst);
351 sprintf(lb,"%s",inst);
352 vsprintf(lb+(strlen(lb)),fmt,ap);
356 while (isspace(*lbp)) lbp++;
359 lineCurr = (lineCurr ?
360 connectLine(lineCurr,newLineNode(lb)) :
361 (lineHead = newLineNode(lb)));
362 lineCurr->isInline = _G.inLine;
363 lineCurr->isDebug = _G.debugLine;
365 // VR fprintf(stderr, "lb = <%s>\n", lbp);
367 // if(pic16_debug_verbose)
368 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
375 /*-----------------------------------------------------------------*/
376 /* pic16_emitDebuggerSymbol - associate the current code location */
377 /* with a debugger symbol */
378 /*-----------------------------------------------------------------*/
380 pic16_emitDebuggerSymbol (char * debugSym)
383 pic16_emitcode (";", "%s ==.", debugSym);
388 /*-----------------------------------------------------------------*/
389 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
390 /*-----------------------------------------------------------------*/
391 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
393 // bool r0iu = FALSE , r1iu = FALSE;
394 // bool r0ou = FALSE , r1ou = FALSE;
395 bool fsr0iu = FALSE, fsr0ou;
396 bool fsr2iu = FALSE, fsr2ou;
398 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
401 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
402 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
404 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
405 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
407 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
408 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
409 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
412 if(!fsr0iu && !fsr0ou) {
413 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
414 (*aopp)->type = AOP_FSR0;
416 fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
418 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
422 /* no usage of FSR2 */
423 if(!fsr2iu && !fsr2ou) {
424 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
425 (*aopp)->type = AOP_FSR2;
427 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
431 /* now we know they both have usage */
432 /* if fsr0 not used in this instruction */
434 if (!_G.fsr0Pushed) {
435 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
436 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
440 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
441 (*aopp)->type = AOP_FSR0;
443 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
445 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
449 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
454 /* the logic: if r0 & r1 used in the instruction
455 then we are in trouble otherwise */
457 /* first check if r0 & r1 are used by this
458 instruction, in which case we are in trouble */
459 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
460 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
465 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
466 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
468 /* if no usage of r0 then return it */
469 if (!r0iu && !r0ou) {
470 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
471 (*aopp)->type = AOP_R0;
473 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
476 /* if no usage of r1 then return it */
477 if (!r1iu && !r1ou) {
478 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
479 (*aopp)->type = AOP_R1;
481 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
484 /* now we know they both have usage */
485 /* if r0 not used in this instruction */
487 /* push it if not already pushed */
489 //pic16_emitcode ("push","%s",
490 // pic16_regWithIdx(R0_IDX)->dname);
494 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
495 (*aopp)->type = AOP_R0;
497 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
500 /* if r1 not used then */
503 /* push it if not already pushed */
505 //pic16_emitcode ("push","%s",
506 // pic16_regWithIdx(R1_IDX)->dname);
510 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
511 (*aopp)->type = AOP_R1;
512 return pic16_regWithIdx(R1_IDX);
516 /* I said end of world but not quite end of world yet */
517 /* if this is a result then we can push it on the stack*/
519 (*aopp)->type = AOP_STK;
523 /* other wise this is true end of the world */
524 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
525 "getFreePtr should never reach here");
530 /*-----------------------------------------------------------------*/
531 /* newAsmop - creates a new asmOp */
532 /*-----------------------------------------------------------------*/
533 static asmop *newAsmop (short type)
537 aop = Safe_calloc(1,sizeof(asmop));
542 static void genSetDPTR(int n)
546 pic16_emitcode(";", "Select standard DPTR");
547 pic16_emitcode("mov", "dps, #0x00");
551 pic16_emitcode(";", "Select alternate DPTR");
552 pic16_emitcode("mov", "dps, #0x01");
556 /*-----------------------------------------------------------------*/
557 /* resolveIfx - converts an iCode ifx into a form more useful for */
558 /* generating code */
559 /*-----------------------------------------------------------------*/
560 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
564 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
570 resIfx->condition = 1; /* assume that the ifx is true */
571 resIfx->generated = 0; /* indicate that the ifx has not been used */
574 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
577 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
578 __FUNCTION__,__LINE__,resIfx->lbl->key);
583 resIfx->lbl = IC_TRUE(ifx);
585 resIfx->lbl = IC_FALSE(ifx);
586 resIfx->condition = 0;
591 DEBUGpic16_emitcode("; +++","ifx true is non-null");
593 DEBUGpic16_emitcode("; +++","ifx true is null");
595 DEBUGpic16_emitcode("; +++","ifx false is non-null");
597 DEBUGpic16_emitcode("; +++","ifx false is null");
601 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
605 /*-----------------------------------------------------------------*/
606 /* pointerCode - returns the code for a pointer type */
607 /*-----------------------------------------------------------------*/
608 static int pointerCode (sym_link *etype)
611 return PTR_TYPE(SPEC_OCLS(etype));
616 /*-----------------------------------------------------------------*/
617 /* aopForSym - for a true symbol */
618 /*-----------------------------------------------------------------*/
619 static asmop *aopForSym (iCode *ic, operand *op, bool result)
621 symbol *sym=OP_SYMBOL(op);
623 memmap *space= SPEC_OCLS(sym->etype);
627 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
629 // sym = OP_SYMBOL(op);
631 /* if already has one */
633 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
638 /* if symbol was initially placed onStack then we must re-place it
639 * to direct memory, since pic16 does not have a specific stack */
641 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
649 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
651 sym->aop = aop = newAsmop (AOP_PAGED);
652 aop->aopu.aop_dir = sym->rname ;
653 aop->size = getSize(sym->type);
654 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
655 pic16_allocDirReg( IC_LEFT(ic) );
663 /* assign depending on the storage class */
664 /* if it is on the stack or indirectly addressable */
665 /* space we need to assign either r0 or r1 to it */
666 if (sym->onStack) // || sym->iaccess)
671 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
672 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
674 /* acquire a temporary register -- it is saved in function */
676 sym->aop = aop = newAsmop(AOP_STA);
677 aop->aopu.stk.stk = sym->stack;
678 aop->size = getSize(sym->type);
681 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
682 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
683 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
684 // pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
686 for(i=0;i<aop->size;i++)
687 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
688 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
690 if(1 && ic->op == SEND) {
692 /* if SEND do the send here */
695 for(i=0;i<aop->size;i++) {
696 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
697 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
702 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
705 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
707 // we do not need to load the value if it is to be defined...
708 if (result) return aop;
711 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
714 for(i=0;i<aop->size;i++) {
716 /* initialise for stack access via frame pointer */
717 // operands on stack are accessible via "FSR2 + index" with index
718 // starting at 2 for arguments and growing from 0 downwards for
719 // local variables (index == 0 is not assigned so we add one here)
721 int soffs = sym->stack;
727 if(1 && ic->op == SEND) {
728 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
729 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
730 pic16_popCopyReg( pic16_frame_plusw ),
731 pic16_popCopyReg(pic16_stack_postdec )));
733 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
734 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
735 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
741 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
748 /* now assign the address of the variable to
749 the pointer register */
750 if (aop->type != AOP_STK) {
754 pic16_emitcode("push","acc");
756 pic16_emitcode("mov","a,_bp");
757 pic16_emitcode("add","a,#0x%02x",
759 ((char)(sym->stack - _G.nRegsSaved )) :
760 ((char)sym->stack)) & 0xff);
761 pic16_emitcode("mov","%s,a",
762 aop->aopu.aop_ptr->name);
765 pic16_emitcode("pop","acc");
767 pic16_emitcode("mov","%s,#%s",
768 aop->aopu.aop_ptr->name,
770 aop->paged = space->paged;
772 aop->aopu.aop_stk = sym->stack;
780 if (sym->onStack && options.stack10bit)
782 /* It's on the 10 bit stack, which is located in
786 //DEBUGpic16_emitcode(";","%d",__LINE__);
789 pic16_emitcode("push","acc");
791 pic16_emitcode("mov","a,_bp");
792 pic16_emitcode("add","a,#0x%02x",
794 ((char)(sym->stack - _G.nRegsSaved )) :
795 ((char)sym->stack)) & 0xff);
798 pic16_emitcode ("mov","dpx1,#0x40");
799 pic16_emitcode ("mov","dph1,#0x00");
800 pic16_emitcode ("mov","dpl1, a");
804 pic16_emitcode("pop","acc");
806 sym->aop = aop = newAsmop(AOP_DPTR2);
807 aop->size = getSize(sym->type);
813 /* special case for a function */
814 if (IS_FUNC(sym->type)) {
815 sym->aop = aop = newAsmop(AOP_PCODE);
816 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
817 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
818 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
819 PCOI(aop->aopu.pcop)->index = 0;
820 aop->size = FPTRSIZE;
821 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
828 //DEBUGpic16_emitcode(";","%d",__LINE__);
829 /* if in bit space */
830 if (IN_BITSPACE(space)) {
831 sym->aop = aop = newAsmop (AOP_CRY);
832 aop->aopu.aop_dir = sym->rname ;
833 aop->size = getSize(sym->type);
834 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
837 /* if it is in direct space */
838 if (IN_DIRSPACE(space)) {
839 sym->aop = aop = newAsmop (AOP_DIR);
840 aop->aopu.aop_dir = sym->rname ;
841 aop->size = getSize(sym->type);
842 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
843 pic16_allocDirReg( IC_LEFT(ic) );
848 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
849 sym->aop = aop = newAsmop (AOP_DIR);
850 aop->aopu.aop_dir = sym->rname ;
851 aop->size = getSize(sym->type);
852 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
853 pic16_allocDirReg( IC_LEFT(ic) );
858 /* only remaining is far space */
859 sym->aop = aop = newAsmop(AOP_PCODE);
861 /* change the next if to 1 to revert to good old immediate code */
862 if(IN_CODESPACE(space)) {
863 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
864 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
865 PCOI(aop->aopu.pcop)->index = 0;
867 /* try to allocate via direct register */
868 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
869 // aop->size = getSize( sym->type );
872 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
873 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
876 if(!pic16_allocDirReg (IC_LEFT(ic)))
880 if(IN_DIRSPACE( space ))
882 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
883 aop->size = FPTRSIZE;
884 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
885 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
886 else if(sym->onStack) {
889 if(SPEC_SCLS(sym->etype) == S_PDATA) {
890 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
891 aop->size = FPTRSIZE;
896 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
898 /* if it is in code space */
899 if (IN_CODESPACE(space))
905 /*-----------------------------------------------------------------*/
906 /* aopForRemat - rematerialzes an object */
907 /*-----------------------------------------------------------------*/
908 static asmop *aopForRemat (operand *op) // x symbol *sym)
910 symbol *sym = OP_SYMBOL(op);
912 iCode *ic = NULL, *oldic;
913 asmop *aop = newAsmop(AOP_PCODE);
920 ic = sym->rematiCode;
922 if(IS_OP_POINTER(op)) {
923 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
929 // pic16_emitpcomment("ic: %s\n", printILine(ic));
932 val += (int) operandLitValue(IC_RIGHT(ic));
933 } else if (ic->op == '-') {
934 val -= (int) operandLitValue(IC_RIGHT(ic));
938 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
941 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
944 if(!op->isaddr)viaimmd++; else viaimmd=0;
946 /* set the following if to 1 to revert to good old immediate code */
947 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
950 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
952 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
955 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
957 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
960 PCOI(aop->aopu.pcop)->index = val;
962 aop->size = getSize( sym->type );
964 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
966 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
967 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
969 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
973 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
974 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
976 val, IS_PTR_CONST(operandType(op)));
978 val, IS_CODEPTR(operandType(op)));
981 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
983 pic16_allocDirReg (IC_LEFT(ic));
985 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
992 static int aopIdx (asmop *aop, int offset)
997 if(aop->type != AOP_REG)
1000 return aop->aopu.aop_reg[offset]->rIdx;
1005 /*-----------------------------------------------------------------*/
1006 /* regsInCommon - two operands have some registers in common */
1007 /*-----------------------------------------------------------------*/
1008 static bool regsInCommon (operand *op1, operand *op2)
1010 symbol *sym1, *sym2;
1013 /* if they have registers in common */
1014 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1017 sym1 = OP_SYMBOL(op1);
1018 sym2 = OP_SYMBOL(op2);
1020 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1023 for (i = 0 ; i < sym1->nRegs ; i++) {
1028 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1032 if (sym2->regs[j] == sym1->regs[i])
1040 /*-----------------------------------------------------------------*/
1041 /* operandsEqu - equivalent */
1042 /*-----------------------------------------------------------------*/
1043 static bool operandsEqu ( operand *op1, operand *op2)
1045 symbol *sym1, *sym2;
1047 /* if they not symbols */
1048 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1051 sym1 = OP_SYMBOL(op1);
1052 sym2 = OP_SYMBOL(op2);
1054 /* if both are itemps & one is spilt
1055 and the other is not then false */
1056 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1057 sym1->isspilt != sym2->isspilt )
1060 /* if they are the same */
1064 if (sym1->rname[0] && sym2->rname[0]
1065 && strcmp (sym1->rname, sym2->rname) == 0)
1069 /* if left is a tmp & right is not */
1070 if (IS_ITEMP(op1) &&
1073 (sym1->usl.spillLoc == sym2))
1076 if (IS_ITEMP(op2) &&
1080 (sym2->usl.spillLoc == sym1))
1086 /*-----------------------------------------------------------------*/
1087 /* pic16_sameRegs - two asmops have the same registers */
1088 /*-----------------------------------------------------------------*/
1089 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1096 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1097 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1099 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1101 if (aop1->type != AOP_REG ||
1102 aop2->type != AOP_REG )
1105 /* This is a bit too restrictive if one is a subset of the other...
1106 if (aop1->size != aop2->size )
1110 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1111 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1113 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1114 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1121 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1123 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1124 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1126 if(aop1 == aop2)return TRUE;
1127 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1129 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1135 /*-----------------------------------------------------------------*/
1136 /* pic16_aopOp - allocates an asmop for an operand : */
1137 /*-----------------------------------------------------------------*/
1138 void pic16_aopOp (operand *op, iCode *ic, bool result)
1147 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1149 /* if this a literal */
1150 if (IS_OP_LITERAL(op)) {
1151 op->aop = aop = newAsmop(AOP_LIT);
1152 aop->aopu.aop_lit = op->operand.valOperand;
1153 aop->size = getSize(operandType(op));
1158 sym_link *type = operandType(op);
1160 if(IS_PTR_CONST(type))
1162 if(IS_CODEPTR(type))
1164 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1167 /* if already has a asmop then continue */
1171 /* if the underlying symbol has a aop */
1172 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1173 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1174 op->aop = OP_SYMBOL(op)->aop;
1178 /* if this is a true symbol */
1179 if (IS_TRUE_SYMOP(op)) {
1180 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1181 op->aop = aopForSym(ic, op, result);
1185 /* this is a temporary : this has
1191 e) can be a return use only */
1193 sym = OP_SYMBOL(op);
1195 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1196 /* if the type is a conditional */
1197 if (sym->regType == REG_CND) {
1198 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1203 /* if it is spilt then two situations
1205 b) has a spill location */
1206 if (sym->isspilt || sym->nRegs == 0) {
1208 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1209 DEBUGpic16_emitcode(";","%d",__LINE__);
1210 /* rematerialize it NOW */
1213 sym->aop = op->aop = aop = aopForRemat (op);
1214 // aop->size = getSize(sym->type);
1215 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1222 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1223 aop->size = getSize(sym->type);
1224 for ( i = 0 ; i < 1 ; i++ ) {
1225 aop->aopu.aop_str[i] = accUse[i];
1226 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1228 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1229 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1237 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1238 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1239 //pic16_allocDirReg (IC_LEFT(ic));
1240 aop->size = getSize(sym->type);
1245 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1246 aop->size = getSize(sym->type);
1247 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1248 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1250 DEBUGpic16_emitcode(";","%d",__LINE__);
1254 /* else spill location */
1255 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1256 /* force a new aop if sizes differ */
1257 sym->usl.spillLoc->aop = NULL;
1261 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1262 __FUNCTION__,__LINE__,
1263 sym->usl.spillLoc->rname,
1264 sym->rname, sym->usl.spillLoc->offset);
1267 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1268 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1269 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1270 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1272 sym->usl.spillLoc->offset, op);
1274 fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1275 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1276 assert (getSize(sym->type) <= 1);
1277 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1279 aop->size = getSize(sym->type);
1285 sym_link *type = operandType(op);
1287 if(IS_PTR_CONST(type))
1289 if(IS_CODEPTR(type))
1291 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1294 /* must be in a register */
1295 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1296 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1297 aop->size = sym->nRegs;
1298 for ( i = 0 ; i < sym->nRegs ;i++)
1299 aop->aopu.aop_reg[i] = sym->regs[i];
1302 /*-----------------------------------------------------------------*/
1303 /* pic16_freeAsmop - free up the asmop given to an operand */
1304 /*----------------------------------------------------------------*/
1305 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1322 /* depending on the asmop type only three cases need work AOP_RO
1323 , AOP_R1 && AOP_STK */
1325 switch (aop->type) {
1327 if (_G.fsr0Pushed ) {
1329 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1330 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1331 // pic16_emitcode ("pop","ar0");
1335 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1339 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1345 pic16_emitcode ("pop","ar0");
1349 bitVectUnSetBit(ic->rUsed,R0_IDX);
1355 pic16_emitcode ("pop","ar1");
1359 bitVectUnSetBit(ic->rUsed,R1_IDX);
1366 /* we must store the result on stack */
1367 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1368 // operands on stack are accessible via "FSR2 + index" with index
1369 // starting at 2 for arguments and growing from 0 downwards for
1370 // local variables (index == 0 is not assigned so we add one here)
1371 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1376 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1377 for(i=0;i<aop->size;i++) {
1378 /* initialise for stack access via frame pointer */
1379 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1380 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1381 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1384 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1388 for(i=0;i<aop->size;i++) {
1389 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1391 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1392 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1403 int stk = aop->aopu.aop_stk + aop->size;
1404 bitVectUnSetBit(ic->rUsed,R0_IDX);
1405 bitVectUnSetBit(ic->rUsed,R1_IDX);
1407 getFreePtr(ic,&aop,FALSE);
1409 if (options.stack10bit)
1411 /* I'm not sure what to do here yet... */
1414 "*** Warning: probably generating bad code for "
1415 "10 bit stack mode.\n");
1419 pic16_emitcode ("mov","a,_bp");
1420 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1421 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1423 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1427 pic16_emitcode("pop","acc");
1428 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1430 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1433 pic16_freeAsmop(op,NULL,ic,TRUE);
1435 pic16_emitcode("pop","ar0");
1440 pic16_emitcode("pop","ar1");
1450 /* all other cases just dealloc */
1454 OP_SYMBOL(op)->aop = NULL;
1455 /* if the symbol has a spill */
1457 SPIL_LOC(op)->aop = NULL;
1462 /*-----------------------------------------------------------------*/
1463 /* pic16_aopGet - for fetching value of the aop */
1464 /*-----------------------------------------------------------------*/
1465 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1470 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1472 /* offset is greater than size then zero */
1473 if (offset > (aop->size - 1) &&
1474 aop->type != AOP_LIT)
1477 /* depending on type */
1478 switch (aop->type) {
1482 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1483 rs = Safe_calloc(1, strlen(s)+1);
1488 /* if we need to increment it */
1489 while (offset > aop->coff)
1491 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1495 while (offset < aop->coff)
1497 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1503 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1504 return (dname ? "acc" : "a");
1506 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1507 rs = Safe_calloc (1, strlen (s) + 1);
1515 sprintf (s,"%s",aop->aopu.aop_immd);
1518 sprintf(s,"(%s >> %d)",
1523 aop->aopu.aop_immd);
1524 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1525 rs = Safe_calloc(1,strlen(s)+1);
1531 sprintf(s,"(%s + %d)",
1534 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1536 sprintf(s,"%s",aop->aopu.aop_dir);
1537 rs = Safe_calloc(1,strlen(s)+1);
1543 // return aop->aopu.aop_reg[offset]->dname;
1545 return aop->aopu.aop_reg[offset]->name;
1548 //pic16_emitcode(";","%d",__LINE__);
1549 return aop->aopu.aop_dir;
1552 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1553 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1555 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1556 rs = Safe_strdup("WREG");
1560 sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1561 rs = Safe_calloc(1,strlen(s)+1);
1566 aop->coff = offset ;
1568 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1571 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1572 aop->type = AOP_ACC;
1573 return Safe_strdup("WREG");
1575 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1577 return aop->aopu.aop_str[offset];
1581 pCodeOp *pcop = aop->aopu.pcop;
1582 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1584 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1585 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1587 sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1589 sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1592 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1595 rs = Safe_calloc(1,strlen(s)+1);
1601 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1603 sprintf(s,"(%s + %d)",
1607 sprintf(s,"%s",aop->aopu.aop_dir);
1608 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1609 rs = Safe_calloc(1,strlen(s)+1);
1615 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1619 // pCodeOp *pcop = aop->aop
1624 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1625 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1626 "aopget got unsupported aop->type");
1632 /* lock has the following meaning: When allocating temporary registers
1633 * for stack variables storage, the value of the temporary register is
1634 * saved on stack. Its value is restored at the end. This procedure is
1635 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1636 * a possibility that before a call to pic16_aopOp, a temporary register
1637 * is allocated for a while and it is freed after some time, this will
1638 * mess the stack and values will not be restored properly. So use lock=1
1639 * to allocate temporary registers used internally by the programmer, and
1640 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1641 * to inform the compiler developer about a possible bug. This is an internal
1642 * feature for developing the compiler -- VR */
1644 int _TempReg_lock = 0;
1645 /*-----------------------------------------------------------------*/
1646 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1647 /*-----------------------------------------------------------------*/
1648 pCodeOp *pic16_popGetTempReg(int lock)
1653 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1655 // werror(W_POSSBUG2, __FILE__, __LINE__);
1658 _TempReg_lock += lock;
1663 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1664 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1665 PCOR(pcop)->r->wasUsed=1;
1666 PCOR(pcop)->r->isFree=0;
1668 /* push value on stack */
1669 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1677 /*-----------------------------------------------------------------*/
1678 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1679 /* is not part of f, but don't save if */
1681 /*-----------------------------------------------------------------*/
1682 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1688 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1691 // werror(W_POSSBUG2, __FILE__, __LINE__);
1694 _TempReg_lock += lock;
1699 i = bitVectFirstBit(f);
1702 /* bypass registers that are used by function */
1703 if(!bitVectBitValue(f, i)) {
1705 /* bypass registers that are already allocated for stack access */
1706 if(!bitVectBitValue(v, i)) {
1708 // debugf("getting register rIdx = %d\n", i);
1709 /* ok, get the operand */
1710 pcop = pic16_newpCodeOpReg( i );
1712 /* should never by NULL */
1713 assert( pcop != NULL );
1717 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1720 PCOR(pcop)->r->wasUsed=1;
1721 PCOR(pcop)->r->isFree=0;
1727 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1729 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1730 /* already used in previous steps, break */
1737 /* caller takes care of the following */
1738 // bitVectSetBit(v, i);
1741 /* push value on stack */
1742 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1743 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1759 /*-----------------------------------------------------------------*/
1760 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1761 /*-----------------------------------------------------------------*/
1762 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1764 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1766 _TempReg_lock -= lock;
1768 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1769 PCOR(pcop)->r->isFree = 1;
1771 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1774 /*-----------------------------------------------------------------*/
1775 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1776 /*-----------------------------------------------------------------*/
1777 pCodeOp *pic16_popGetLabel(unsigned int key)
1780 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1785 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1788 /*-----------------------------------------------------------------*/
1789 /* pic16_popCopyReg - copy a pcode operator */
1790 /*-----------------------------------------------------------------*/
1791 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1795 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1796 memcpy (pcor, pc, sizeof (pCodeOpReg));
1797 pcor->r->wasUsed = 1;
1799 //pcor->pcop.type = pc->pcop.type;
1801 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1802 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1804 pcor->pcop.name = NULL;
1807 //pcor->rIdx = pc->rIdx;
1808 //pcor->r->wasUsed=1;
1809 //pcor->instance = pc->instance;
1811 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1816 /*-----------------------------------------------------------------*/
1817 /* pic16_popGetLit - asm operator to pcode operator conversion */
1818 /*-----------------------------------------------------------------*/
1819 pCodeOp *pic16_popGetLit(int lit)
1821 return pic16_newpCodeOpLit(lit);
1824 /*-----------------------------------------------------------------*/
1825 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1826 /*-----------------------------------------------------------------*/
1827 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1829 return pic16_newpCodeOpLit2(lit, arg2);
1833 /*-----------------------------------------------------------------*/
1834 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1835 /*-----------------------------------------------------------------*/
1836 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1838 return pic16_newpCodeOpImmd(name, offset,index, 0);
1842 /*-----------------------------------------------------------------*/
1843 /* pic16_popGet - asm operator to pcode operator conversion */
1844 /*-----------------------------------------------------------------*/
1845 pCodeOp *pic16_popGetWithString(char *str)
1851 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1855 pcop = pic16_newpCodeOp(str,PO_STR);
1860 /*-----------------------------------------------------------------*/
1861 /* pic16_popRegFromString - */
1862 /*-----------------------------------------------------------------*/
1863 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1866 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1867 pcop->type = PO_DIR;
1869 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1870 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1875 pcop->name = Safe_calloc(1,strlen(str)+1);
1876 strcpy(pcop->name,str);
1878 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1880 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1882 /* make sure that register doesn't exist,
1883 * and operand isn't NULL
1884 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1885 if((PCOR(pcop)->r == NULL)
1887 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1888 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1889 // __FUNCTION__, __LINE__, str, size, offset);
1891 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1892 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1895 PCOR(pcop)->instance = offset;
1900 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1904 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1906 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1907 PCOR(pcop)->rIdx = rIdx;
1908 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1910 PCOR(pcop)->r->isFree = 0;
1911 PCOR(pcop)->r->wasUsed = 1;
1913 pcop->type = PCOR(pcop)->r->pc_type;
1918 /*---------------------------------------------------------------------------------*/
1919 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1921 /*---------------------------------------------------------------------------------*/
1922 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1927 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1929 /* comment the following check, so errors to throw up */
1930 // if(!pcop2)return NULL;
1932 temp = pic16_popGet(aop_dst, offset);
1933 pcop2->pcop2 = temp;
1940 /*--------------------------------------------------------------------------------.-*/
1941 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1942 /* VR 030601 , adapted by Hans Dorn */
1943 /*--------------------------------------------------------------------------------.-*/
1944 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1948 pcop2 = (pCodeOpReg2 *)src;
1956 /*---------------------------------------------------------------------------------*/
1957 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1958 /* movff instruction */
1959 /*---------------------------------------------------------------------------------*/
1960 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1965 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1966 pcop2->pcop2 = pic16_popCopyReg(dst);
1968 /* the pCodeOp may be already allocated */
1969 pcop2 = (pCodeOpReg2 *)(src);
1970 pcop2->pcop2 = (pCodeOp *)(dst);
1977 /*-----------------------------------------------------------------*/
1978 /* pic16_popGet - asm operator to pcode operator conversion */
1979 /*-----------------------------------------------------------------*/
1980 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1982 //char *s = buffer ;
1987 /* offset is greater than
1990 // if (offset > (aop->size - 1) &&
1991 // aop->type != AOP_LIT)
1992 // return NULL; //zero;
1994 /* depending on type */
1995 switch (aop->type) {
2001 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2002 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2009 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2010 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2011 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2012 PCOR(pcop)->r->wasUsed = 1;
2013 PCOR(pcop)->r->isFree = 0;
2015 PCOR(pcop)->instance = offset;
2016 pcop->type = PCOR(pcop)->r->pc_type;
2020 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2021 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2024 /* pCodeOp is already allocated from aopForSym */
2025 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2026 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2032 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2034 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2036 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2038 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2039 PCOR(pcop)->rIdx = rIdx;
2040 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2041 PCOR(pcop)->r->wasUsed=1;
2042 PCOR(pcop)->r->isFree=0;
2044 PCOR(pcop)->instance = offset;
2045 pcop->type = PCOR(pcop)->r->pc_type;
2046 // rs = aop->aopu.aop_reg[offset]->name;
2047 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2051 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2052 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2058 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2059 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2063 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2064 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2070 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2071 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2073 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2075 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2076 // pcop->type = PO_GPR_REGISTER;
2077 PCOR(pcop)->rIdx = rIdx;
2078 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2079 PCOR(pcop)->r->wasUsed=1;
2080 PCOR(pcop)->r->isFree=0;
2082 PCOR(pcop)->instance = offset;
2083 pcop->type = PCOR(pcop)->r->pc_type;
2085 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2086 rs = aop->aopu.aop_reg[offset]->name;
2087 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2092 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2094 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2095 PCOR(pcop)->instance = offset;
2096 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2097 //if(PCOR(pcop)->r == NULL)
2098 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2102 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2103 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2106 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2107 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2110 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2111 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2112 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2113 pcop->type = PCOR(pcop)->r->pc_type;
2114 pcop->name = PCOR(pcop)->r->name;
2120 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2122 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2123 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2124 switch( aop->aopu.pcop->type ) {
2125 case PO_DIR: PCOR(pcop)->instance += offset; break;
2126 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2131 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2132 assert( 0 ); /* should never reach here */;
2137 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2138 "pic16_popGet got unsupported aop->type");
2141 /*-----------------------------------------------------------------*/
2142 /* pic16_aopPut - puts a string for a aop */
2143 /*-----------------------------------------------------------------*/
2144 void pic16_aopPut (asmop *aop, char *s, int offset)
2151 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2153 if (aop->size && offset > ( aop->size - 1)) {
2154 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2155 "pic16_aopPut got offset > aop->size");
2159 /* will assign value to value */
2160 /* depending on where it is ofcourse */
2161 switch (aop->type) {
2164 sprintf(d,"(%s + %d)",
2165 aop->aopu.aop_dir,offset);
2166 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2169 sprintf(d,"%s",aop->aopu.aop_dir);
2172 DEBUGpic16_emitcode(";","%d",__LINE__);
2174 pic16_emitcode("movf","%s,w",s);
2175 pic16_emitcode("movwf","%s",d);
2178 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2179 if(offset >= aop->size) {
2180 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2183 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2186 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2193 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2194 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2197 strcmp(s,"r0") == 0 ||
2198 strcmp(s,"r1") == 0 ||
2199 strcmp(s,"r2") == 0 ||
2200 strcmp(s,"r3") == 0 ||
2201 strcmp(s,"r4") == 0 ||
2202 strcmp(s,"r5") == 0 ||
2203 strcmp(s,"r6") == 0 ||
2204 strcmp(s,"r7") == 0 )
2205 pic16_emitcode("mov","%s,%s ; %d",
2206 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2210 if(strcmp(s,"W")==0 )
2211 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2213 pic16_emitcode("movwf","%s",
2214 aop->aopu.aop_reg[offset]->name);
2216 if(strcmp(s,zero)==0) {
2217 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2219 } else if(strcmp(s,"W")==0) {
2220 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2221 pcop->type = PO_GPR_REGISTER;
2223 PCOR(pcop)->rIdx = -1;
2224 PCOR(pcop)->r = NULL;
2226 DEBUGpic16_emitcode(";","%d",__LINE__);
2227 pcop->name = Safe_strdup(s);
2228 pic16_emitpcode(POC_MOVFW,pcop);
2229 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2230 } else if(strcmp(s,one)==0) {
2231 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2232 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2234 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2242 if (aop->type == AOP_DPTR2)
2248 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2249 "pic16_aopPut writting to code space");
2253 while (offset > aop->coff) {
2255 pic16_emitcode ("inc","dptr");
2258 while (offset < aop->coff) {
2260 pic16_emitcode("lcall","__decdptr");
2265 /* if not in accumulater */
2268 pic16_emitcode ("movx","@dptr,a");
2270 if (aop->type == AOP_DPTR2)
2278 while (offset > aop->coff) {
2280 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2282 while (offset < aop->coff) {
2284 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2290 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2295 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2297 if (strcmp(s,"r0") == 0 ||
2298 strcmp(s,"r1") == 0 ||
2299 strcmp(s,"r2") == 0 ||
2300 strcmp(s,"r3") == 0 ||
2301 strcmp(s,"r4") == 0 ||
2302 strcmp(s,"r5") == 0 ||
2303 strcmp(s,"r6") == 0 ||
2304 strcmp(s,"r7") == 0 ) {
2306 sprintf(buffer,"a%s",s);
2307 pic16_emitcode("mov","@%s,%s",
2308 aop->aopu.aop_ptr->name,buffer);
2310 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2315 if (strcmp(s,"a") == 0)
2316 pic16_emitcode("push","acc");
2318 pic16_emitcode("push","%s",s);
2323 /* if bit variable */
2324 if (!aop->aopu.aop_dir) {
2325 pic16_emitcode("clr","a");
2326 pic16_emitcode("rlc","a");
2329 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2332 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2335 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2337 lbl = newiTempLabel(NULL);
2339 if (strcmp(s,"a")) {
2342 pic16_emitcode("clr","c");
2343 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2344 pic16_emitcode("cpl","c");
2345 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2346 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2353 if (strcmp(aop->aopu.aop_str[offset],s))
2354 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2359 if (!offset && (strcmp(s,"acc") == 0))
2362 if (strcmp(aop->aopu.aop_str[offset],s))
2363 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2367 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2368 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2369 // "pic16_aopPut got unsupported aop->type");
2375 /*-----------------------------------------------------------------*/
2376 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2377 /*-----------------------------------------------------------------*/
2378 void pic16_mov2w (asmop *aop, int offset)
2380 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2383 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2385 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2388 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2390 if(is_LitAOp(src)) {
2391 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2392 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2394 if(pic16_sameRegsOfs(src, dst, offset))return;
2395 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2396 pic16_popGet(dst, offset)));
2400 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2402 if(is_LitAOp(src)) {
2403 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2404 pic16_emitpcode(POC_MOVWF, dst);
2406 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2410 void pic16_testStackOverflow(void)
2412 #define GSTACK_TEST_NAME "_gstack_test"
2414 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2419 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2420 sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2421 // strcpy(sym->rname, GSTACK_TEST_NAME);
2422 checkAddSym(&externs, sym);
2427 /* push pcop into stack */
2428 void pic16_pushpCodeOp(pCodeOp *pcop)
2430 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2431 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2432 if(pic16_options.gstack)
2433 pic16_testStackOverflow();
2437 /* pop pcop from stack */
2438 void pic16_poppCodeOp(pCodeOp *pcop)
2440 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2441 if(pic16_options.gstack)
2442 pic16_testStackOverflow();
2446 /*-----------------------------------------------------------------*/
2447 /* pushw - pushes wreg to stack */
2448 /*-----------------------------------------------------------------*/
2451 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2452 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2453 if(pic16_options.gstack)
2454 pic16_testStackOverflow();
2458 /*-----------------------------------------------------------------*/
2459 /* pushaop - pushes aop to stack */
2460 /*-----------------------------------------------------------------*/
2461 void pushaop(asmop *aop, int offset)
2463 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2465 if(is_LitAOp(aop)) {
2466 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2467 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2469 pic16_emitpcode(POC_MOVFF,
2470 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2473 if(pic16_options.gstack)
2474 pic16_testStackOverflow();
2477 /*-----------------------------------------------------------------*/
2478 /* popaop - pops aop from stack */
2479 /*-----------------------------------------------------------------*/
2480 void popaop(asmop *aop, int offset)
2482 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2483 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2484 if(pic16_options.gstack)
2485 pic16_testStackOverflow();
2488 void popaopidx(asmop *aop, int offset, int index)
2492 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2494 if(STACK_MODEL_LARGE)ofs++;
2496 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2497 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2498 if(pic16_options.gstack)
2499 pic16_testStackOverflow();
2502 #if !(USE_GENERIC_SIGNED_SHIFT)
2503 /*-----------------------------------------------------------------*/
2504 /* reAdjustPreg - points a register back to where it should */
2505 /*-----------------------------------------------------------------*/
2506 static void reAdjustPreg (asmop *aop)
2510 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2512 if ((size = aop->size) <= 1)
2515 switch (aop->type) {
2519 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2523 if (aop->type == AOP_DPTR2)
2529 pic16_emitcode("lcall","__decdptr");
2532 if (aop->type == AOP_DPTR2)
2544 /*-----------------------------------------------------------------*/
2545 /* opIsGptr: returns non-zero if the passed operand is */
2546 /* a generic pointer type. */
2547 /*-----------------------------------------------------------------*/
2548 static int opIsGptr(operand *op)
2550 sym_link *type = operandType(op);
2552 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2553 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2561 /*-----------------------------------------------------------------*/
2562 /* pic16_getDataSize - get the operand data size */
2563 /*-----------------------------------------------------------------*/
2564 int pic16_getDataSize(operand *op)
2566 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2569 return AOP_SIZE(op);
2571 // tsd- in the pic port, the genptr size is 1, so this code here
2572 // fails. ( in the 8051 port, the size was 4).
2575 size = AOP_SIZE(op);
2576 if (size == GPTRSIZE)
2578 sym_link *type = operandType(op);
2579 if (IS_GENPTR(type))
2581 /* generic pointer; arithmetic operations
2582 * should ignore the high byte (pointer type).
2585 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2592 /*-----------------------------------------------------------------*/
2593 /* pic16_outAcc - output Acc */
2594 /*-----------------------------------------------------------------*/
2595 void pic16_outAcc(operand *result)
2598 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2599 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2602 size = pic16_getDataSize(result);
2604 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2607 /* unsigned or positive */
2609 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2614 /*-----------------------------------------------------------------*/
2615 /* pic16_outBitC - output a bit C */
2616 /* Move to result the value of Carry flag -- VR */
2617 /*-----------------------------------------------------------------*/
2618 void pic16_outBitC(operand *result)
2622 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2624 /* if the result is bit */
2625 if (AOP_TYPE(result) == AOP_CRY) {
2626 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2627 pic16_aopPut(AOP(result),"c",0);
2630 i = AOP_SIZE(result);
2632 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2634 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2638 /*-----------------------------------------------------------------*/
2639 /* pic16_outBitOp - output a bit from Op */
2640 /* Move to result the value of set/clr op -- VR */
2641 /*-----------------------------------------------------------------*/
2642 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2646 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2648 /* if the result is bit */
2649 if (AOP_TYPE(result) == AOP_CRY) {
2650 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2651 pic16_aopPut(AOP(result),"c",0);
2654 i = AOP_SIZE(result);
2656 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2658 pic16_emitpcode(POC_RRCF, pcop);
2659 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2663 /*-----------------------------------------------------------------*/
2664 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2665 /*-----------------------------------------------------------------*/
2666 void pic16_toBoolean(operand *oper)
2668 int size = AOP_SIZE(oper) - 1;
2671 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2673 if ( AOP_TYPE(oper) != AOP_ACC) {
2674 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2677 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2681 /*-----------------------------------------------------------------*/
2682 /* genUminusFloat - unary minus for floating points */
2683 /*-----------------------------------------------------------------*/
2684 static void genUminusFloat(operand *op,operand *result)
2686 int size ,offset =0 ;
2689 /* for this we just need to flip the
2690 first it then copy the rest in place */
2691 size = AOP_SIZE(op);
2692 assert( size == AOP_SIZE(result) );
2695 pic16_mov2f(AOP(result), AOP(op), offset);
2699 /* toggle the MSB's highest bit */
2700 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2703 /*-----------------------------------------------------------------*/
2704 /* genUminus - unary minus code generation */
2705 /*-----------------------------------------------------------------*/
2706 static void genUminus (iCode *ic)
2709 sym_link *optype, *rtype;
2716 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2717 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2719 /* if both in bit space then special case */
2720 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2721 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2723 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2724 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2725 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2729 optype = operandType(IC_LEFT(ic));
2730 rtype = operandType(IC_RESULT(ic));
2733 /* if float then do float stuff */
2734 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2735 if(IS_FIXED(optype))
2736 debugf("implement fixed16x16 type\n", 0);
2738 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2742 /* otherwise subtract from zero by taking the 2's complement */
2743 size = AOP_SIZE(IC_LEFT(ic));
2744 assert( size == AOP_SIZE(IC_RESULT(ic)) );
2745 label = newiTempLabel ( NULL );
2747 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2748 for (i=size-1; i > 0; i--) {
2749 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2751 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2752 for (i=1; i < size; i++) {
2753 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2754 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2757 for (i=size-1; i >= 0; i--) {
2758 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2759 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2762 for (i=0; i < size-2; i++) {
2763 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2764 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2766 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2768 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2771 pic16_emitpLabel (label->key);
2774 /* release the aops */
2775 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2776 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2780 /*-----------------------------------------------------------------*/
2781 /* saveRegisters - will look for a call and save the registers */
2782 /*-----------------------------------------------------------------*/
2783 static void saveRegisters(iCode *lic)
2790 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2792 for (ic = lic ; ic ; ic = ic->next)
2793 if (ic->op == CALL || ic->op == PCALL)
2797 fprintf(stderr,"found parameter push with no function call\n");
2801 /* if the registers have been saved already then
2803 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2806 /* find the registers in use at this time
2807 and push them away to safety */
2808 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2812 if (options.useXstack) {
2813 if (bitVectBitValue(rsave,R0_IDX))
2814 pic16_emitcode("mov","b,r0");
2815 pic16_emitcode("mov","r0,%s",spname);
2816 for (i = 0 ; i < pic16_nRegs ; i++) {
2817 if (bitVectBitValue(rsave,i)) {
2819 pic16_emitcode("mov","a,b");
2821 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2822 pic16_emitcode("movx","@r0,a");
2823 pic16_emitcode("inc","r0");
2826 pic16_emitcode("mov","%s,r0",spname);
2827 if (bitVectBitValue(rsave,R0_IDX))
2828 pic16_emitcode("mov","r0,b");
2830 //for (i = 0 ; i < pic16_nRegs ; i++) {
2831 // if (bitVectBitValue(rsave,i))
2832 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2835 dtype = operandType(IC_LEFT(ic));
2836 if (currFunc && dtype &&
2837 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2838 IFFUNC_ISISR(currFunc->type) &&
2841 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2844 /*-----------------------------------------------------------------*/
2845 /* unsaveRegisters - pop the pushed registers */
2846 /*-----------------------------------------------------------------*/
2847 static void unsaveRegisters (iCode *ic)
2852 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2853 /* find the registers in use at this time
2854 and push them away to safety */
2855 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2858 if (options.useXstack) {
2859 pic16_emitcode("mov","r0,%s",spname);
2860 for (i = pic16_nRegs ; i >= 0 ; i--) {
2861 if (bitVectBitValue(rsave,i)) {
2862 pic16_emitcode("dec","r0");
2863 pic16_emitcode("movx","a,@r0");
2865 pic16_emitcode("mov","b,a");
2867 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2871 pic16_emitcode("mov","%s,r0",spname);
2872 if (bitVectBitValue(rsave,R0_IDX))
2873 pic16_emitcode("mov","r0,b");
2875 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2876 // if (bitVectBitValue(rsave,i))
2877 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2884 /*-----------------------------------------------------------------*/
2886 /*-----------------------------------------------------------------*/
2887 static void pushSide(operand * oper, int size)
2890 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2892 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2893 if (AOP_TYPE(oper) != AOP_REG &&
2894 AOP_TYPE(oper) != AOP_DIR &&
2896 pic16_emitcode("mov","a,%s",l);
2897 pic16_emitcode("push","acc");
2899 pic16_emitcode("push","%s",l);
2904 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2906 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2907 pic16_emitpcode(POC_MOVFW, src);
2908 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2910 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2911 src, pic16_popGet(AOP(op), offset)));
2916 /*-----------------------------------------------------------------*/
2917 /* assignResultValue - assign results to oper, rescall==1 is */
2918 /* called from genCall() or genPcall() */
2919 /*-----------------------------------------------------------------*/
2920 static void assignResultValue(operand * oper, int rescall)
2922 int size = AOP_SIZE(oper);
2926 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2927 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2930 /* assign result from a call/pcall function() */
2932 /* function results are stored in a special order,
2933 * see top of file with Function return policy, or manual */
2936 /* 8-bits, result in WREG */
2937 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2940 /* 16-bits, result in PRODL:WREG */
2941 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2945 /* 24-bits, result in PRODH:PRODL:WREG */
2946 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2950 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2951 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2955 /* >32-bits, result on stack, and FSR0 points to beginning.
2956 * Fix stack when done */
2958 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2960 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2961 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2963 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2968 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2969 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
2970 if(STACK_MODEL_LARGE) {
2972 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
2976 int areg = 0; /* matching argument register */
2978 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2979 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2982 /* its called from genReceive (probably) -- VR */
2983 /* I hope this code will not be called from somewhere else in the future!
2984 * We manually set the pseudo stack pointer in genReceive. - dw
2986 if(!GpsuedoStkPtr && _G.useWreg) {
2987 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2989 /* The last byte in the assignment is in W */
2990 if(areg <= GpsuedoStkPtr) {
2992 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2994 // debugf("receive from WREG\n", 0);
2996 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2999 _G.stack_lat = AOP_SIZE(oper)-1;
3004 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3005 // debugf("receive from STACK\n", 0);
3012 /*-----------------------------------------------------------------*/
3013 /* genIpush - generate code for pushing this gets a little complex */
3014 /*-----------------------------------------------------------------*/
3015 static void genIpush (iCode *ic)
3017 // int size, offset=0;
3020 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3023 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3025 /* send to stack as normal */
3026 addSet(&_G.sendSet,ic);
3027 // addSetHead(&_G.sendSet,ic);
3028 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3033 int size, offset = 0 ;
3037 /* if this is not a parm push : ie. it is spill push
3038 and spill push is always done on the local stack */
3039 if (!ic->parmPush) {
3041 /* and the item is spilt then do nothing */
3042 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3045 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3046 size = AOP_SIZE(IC_LEFT(ic));
3047 /* push it on the stack */
3049 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3054 pic16_emitcode("push","%s",l);
3059 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3063 /*-----------------------------------------------------------------*/
3064 /* genIpop - recover the registers: can happen only for spilling */
3065 /*-----------------------------------------------------------------*/
3066 static void genIpop (iCode *ic)
3069 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3074 /* if the temp was not pushed then */
3075 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3078 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3079 size = AOP_SIZE(IC_LEFT(ic));
3082 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3085 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3090 /*-----------------------------------------------------------------*/
3091 /* unsaverbank - restores the resgister bank from stack */
3092 /*-----------------------------------------------------------------*/
3093 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3095 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3101 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3103 if (options.useXstack) {
3105 r = getFreePtr(ic,&aop,FALSE);
3108 pic16_emitcode("mov","%s,_spx",r->name);
3109 pic16_emitcode("movx","a,@%s",r->name);
3110 pic16_emitcode("mov","psw,a");
3111 pic16_emitcode("dec","%s",r->name);
3114 pic16_emitcode ("pop","psw");
3117 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3118 if (options.useXstack) {
3119 pic16_emitcode("movx","a,@%s",r->name);
3120 //pic16_emitcode("mov","(%s+%d),a",
3121 // regspic16[i].base,8*bank+regspic16[i].offset);
3122 pic16_emitcode("dec","%s",r->name);
3125 pic16_emitcode("pop",""); //"(%s+%d)",
3126 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3129 if (options.useXstack) {
3131 pic16_emitcode("mov","_spx,%s",r->name);
3132 pic16_freeAsmop(NULL,aop,ic,TRUE);
3138 /*-----------------------------------------------------------------*/
3139 /* saverbank - saves an entire register bank on the stack */
3140 /*-----------------------------------------------------------------*/
3141 static void saverbank (int bank, iCode *ic, bool pushPsw)
3143 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3149 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3150 if (options.useXstack) {
3153 r = getFreePtr(ic,&aop,FALSE);
3154 pic16_emitcode("mov","%s,_spx",r->name);
3158 for (i = 0 ; i < pic16_nRegs ;i++) {
3159 if (options.useXstack) {
3160 pic16_emitcode("inc","%s",r->name);
3161 //pic16_emitcode("mov","a,(%s+%d)",
3162 // regspic16[i].base,8*bank+regspic16[i].offset);
3163 pic16_emitcode("movx","@%s,a",r->name);
3165 pic16_emitcode("push","");// "(%s+%d)",
3166 //regspic16[i].base,8*bank+regspic16[i].offset);
3170 if (options.useXstack) {
3171 pic16_emitcode("mov","a,psw");
3172 pic16_emitcode("movx","@%s,a",r->name);
3173 pic16_emitcode("inc","%s",r->name);
3174 pic16_emitcode("mov","_spx,%s",r->name);
3175 pic16_freeAsmop (NULL,aop,ic,TRUE);
3178 pic16_emitcode("push","psw");
3180 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3188 static int wparamCmp(void *p1, void *p2)
3190 return (!strcmp((char *)p1, (char *)p2));
3193 int inWparamList(char *s)
3195 return isinSetWith(wparamList, s, wparamCmp);
3199 /*-----------------------------------------------------------------*/
3200 /* genCall - generates a call statement */
3201 /*-----------------------------------------------------------------*/
3202 static void genCall (iCode *ic)
3212 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3213 /* if caller saves & we have not saved then */
3214 // if (!ic->regsSaved)
3215 // saveRegisters(ic);
3217 /* initialise stackParms for IPUSH pushes */
3218 // stackParms = psuedoStkPtr;
3219 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3220 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3221 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3224 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3227 /* if send set is not empty the assign */
3230 int psuedoStkPtr=-1;
3231 int firstTimeThruLoop = 1;
3234 /* reverse sendSet if function is not reentrant */
3235 if(!IFFUNC_ISREENT(ftype))
3236 _G.sendSet = reverseSet(_G.sendSet);
3238 /* First figure how many parameters are getting passed */
3242 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3246 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3247 size = AOP_SIZE(IC_LEFT(sic));
3251 /* pass the last byte through WREG */
3255 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3256 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3257 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3259 if(!firstTimeThruLoop) {
3260 /* If this is not the first time we've been through the loop
3261 * then we need to save the parameter in a temporary
3262 * register. The last byte of the last parameter is
3266 // --psuedoStkPtr; // sanity check
3270 firstTimeThruLoop=0;
3272 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3277 /* all arguments are passed via stack */
3281 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3282 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3283 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3285 // pushaop(AOP(IC_LEFT(sic)), size);
3286 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3293 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3297 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3298 pushw(); /* save last parameter to stack if functions has varargs */
3302 } else use_wreg = 0;
3304 _G.stackRegSet = _G.sendSet;
3309 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3313 /* if we need to assign a result value */
3314 if ((IS_ITEMP(IC_RESULT(ic))
3315 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3316 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3317 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3320 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3323 assignResultValue(IC_RESULT(ic), 1);
3325 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3326 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3328 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3331 if(!stackParms && ic->parmBytes) {
3332 stackParms = ic->parmBytes;
3335 stackParms -= use_wreg;
3338 if(stackParms == 1) {
3339 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3341 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3342 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3344 if(STACK_MODEL_LARGE) {
3346 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3351 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3354 /* adjust the stack for parameters if required */
3355 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3358 /* if register bank was saved then pop them */
3360 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3362 /* if we hade saved some registers then unsave them */
3363 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3364 unsaveRegisters (ic);
3370 /*-----------------------------------------------------------------*/
3371 /* genPcall - generates a call by pointer statement */
3372 /* new version, created from genCall - HJD */
3373 /*-----------------------------------------------------------------*/
3374 static void genPcall (iCode *ic)
3376 sym_link *ftype, *fntype;
3378 symbol *retlbl = newiTempLabel(NULL);
3379 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3383 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3384 fntype = operandType( IC_LEFT(ic) )->next;
3386 /* if send set is not empty the assign */
3389 int psuedoStkPtr=-1;
3391 /* reverse sendSet if function is not reentrant */
3392 if(!IFFUNC_ISREENT(fntype))
3393 _G.sendSet = reverseSet(_G.sendSet);
3397 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3400 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3401 size = AOP_SIZE(IC_LEFT(sic));
3404 /* all parameters are passed via stack, since WREG is clobbered
3405 * by the calling sequence */
3407 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3408 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3409 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3411 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3415 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3418 _G.stackRegSet = _G.sendSet;
3422 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3424 // push return address
3425 // push $ on return stack, then replace with retlbl
3427 /* Thanks to Thorsten Klose for pointing out that the following
3428 * snippet should be interrupt safe */
3429 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3430 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3432 pic16_emitpcodeNULLop(POC_PUSH);
3434 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3435 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3436 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3437 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3438 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3439 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3442 /* restore interrupt control register */
3443 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3444 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3446 /* make the call by writing the pointer into pc */
3447 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3448 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3450 // note: MOVFF to PCL not allowed
3451 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3452 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3455 /* return address is here: (X) */
3456 pic16_emitpLabelFORCE(retlbl->key);
3458 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3461 /* if we need assign a result value */
3462 if ((IS_ITEMP(IC_RESULT(ic))
3463 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3464 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3465 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3468 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3471 assignResultValue(IC_RESULT(ic), 1);
3473 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3474 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3476 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3479 // stackParms -= use_wreg;
3482 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3483 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3484 if(STACK_MODEL_LARGE) {
3486 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3491 /*-----------------------------------------------------------------*/
3492 /* resultRemat - result is rematerializable */
3493 /*-----------------------------------------------------------------*/
3494 static int resultRemat (iCode *ic)
3496 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3497 if (SKIP_IC(ic) || ic->op == IFX)
3500 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3501 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3502 if (sym->remat && !POINTER_SET(ic))
3509 #if defined(__BORLANDC__) || defined(_MSC_VER)
3510 #define STRCASECMP stricmp
3512 #define STRCASECMP strcasecmp
3516 /*-----------------------------------------------------------------*/
3517 /* inExcludeList - return 1 if the string is in exclude Reg list */
3518 /*-----------------------------------------------------------------*/
3519 static bool inExcludeList(char *s)
3521 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3524 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3525 if (options.excludeRegs[i] &&
3526 STRCASECMP(options.excludeRegs[i],"none") == 0)
3529 for ( i = 0 ; options.excludeRegs[i]; i++) {
3530 if (options.excludeRegs[i] &&
3531 STRCASECMP(s,options.excludeRegs[i]) == 0)
3538 /*-----------------------------------------------------------------*/
3539 /* genFunction - generated code for function entry */
3540 /*-----------------------------------------------------------------*/
3541 static void genFunction (iCode *ic)
3547 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3549 pic16_labelOffset += (max_key+4);
3554 ftype = operandType(IC_LEFT(ic));
3555 sym = OP_SYMBOL(IC_LEFT(ic));
3557 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3558 /* create an absolute section at the interrupt vector:
3559 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3564 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3566 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3567 sprintf(asymname, "ivec_%s", sym->name);
3569 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3571 /* when an interrupt is declared as naked, do not emit the special
3572 * wrapper segment at vector address. The user should take care for
3573 * this instead. -- VR */
3575 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3576 asym = newSymbol(asymname, 0);
3577 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3578 pic16_addpBlock( apb );
3580 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3581 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3582 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3583 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3584 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3586 /* mark the end of this tiny function */
3587 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3589 sprintf(asymname, "%s", sym->rname);
3595 abSym = Safe_calloc(1, sizeof(absSym));
3596 strcpy(abSym->name, asymname);
3598 switch( FUNC_INTNO(sym->type) ) {
3599 case 0: abSym->address = 0x000000; break;
3600 case 1: abSym->address = 0x000008; break;
3601 case 2: abSym->address = 0x000018; break;
3604 // fprintf(stderr, "no interrupt number is given\n");
3605 abSym->address = -1; break;
3608 /* relocate interrupt vectors if needed */
3609 if(abSym->address != -1)
3610 abSym->address += pic16_options.ivt_loc;
3612 addSet(&absSymSet, abSym);
3616 /* create the function header */
3617 pic16_emitcode(";","-----------------------------------------");
3618 pic16_emitcode(";"," function %s",sym->name);
3619 pic16_emitcode(";","-----------------------------------------");
3621 pic16_emitcode("","%s:",sym->rname);
3622 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3627 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3628 if(!strcmp(ab->name, sym->rname)) {
3629 pic16_pBlockConvert2Absolute(pb);
3635 if(IFFUNC_ISNAKED(ftype)) {
3636 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3640 /* if critical function then turn interrupts off */
3641 if (IFFUNC_ISCRITICAL(ftype)) {
3642 //pic16_emitcode("clr","ea");
3645 currFunc = sym; /* update the currFunc symbol */
3646 _G.fregsUsed = sym->regsUsed;
3647 _G.sregsAlloc = newBitVect(128);
3650 /* if this is an interrupt service routine then
3651 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3652 if (IFFUNC_ISISR(sym->type)) {
3653 _G.usefastretfie = 1; /* use shadow registers by default */
3655 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3656 if(!FUNC_ISSHADOWREGS(sym->type)) {
3657 /* do not save WREG,STATUS,BSR for high priority interrupts
3658 * because they are stored in the hardware shadow registers already */
3659 _G.usefastretfie = 0;
3660 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3661 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3662 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3665 /* these should really be optimized somehow, because not all
3666 * interrupt handlers modify them */
3667 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3668 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3669 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3670 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3672 // pic16_pBlockConvert2ISR(pb);
3675 /* emit code to setup stack frame if user enabled,
3676 * and function is not main() */
3678 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3679 if(strcmp(sym->name, "main")) {
3681 || !options.ommitFramePtr
3683 || IFFUNC_ARGS(sym->type)
3684 || FUNC_HASSTACKPARM(sym->etype)
3686 /* setup the stack frame */
3687 if(STACK_MODEL_LARGE)
3688 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3689 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3691 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3692 if(STACK_MODEL_LARGE)
3693 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3697 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3700 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3702 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3703 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3705 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3708 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3709 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3716 /* if callee-save to be used for this function
3717 * then save the registers being used in this function */
3718 // if (IFFUNC_CALLEESAVES(sym->type))
3722 /* if any registers used */
3723 if (sym->regsUsed) {
3724 /* save the registers used */
3725 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3726 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3727 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3728 if (bitVectBitValue(sym->regsUsed,i)) {
3729 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3732 if(!pic16_regWithIdx(i)->wasUsed) {
3733 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3734 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3735 pic16_regWithIdx(i)->wasUsed = 1;
3739 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3743 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3744 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3747 /*-----------------------------------------------------------------*/
3748 /* genEndFunction - generates epilogue for functions */
3749 /*-----------------------------------------------------------------*/
3750 static void genEndFunction (iCode *ic)
3752 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3756 if(IFFUNC_ISNAKED(sym->type)) {
3757 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3763 /* add code for ISCRITICAL */
3764 if(IFFUNC_ISCRITICAL(sym->type)) {
3765 /* if critical function, turn on interrupts */
3767 /* TODO: add code here -- VR */
3770 // sym->regsUsed = _G.fregsUsed;
3772 /* now we need to restore the registers */
3773 /* if any registers used */
3775 /* first restore registers that might be used for stack access */
3776 if(_G.sregsAllocSet) {
3779 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3780 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3781 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3785 if (sym->regsUsed) {
3788 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3789 /* restore registers used */
3790 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3791 for ( i = sym->regsUsed->size; i >= 0; i--) {
3792 if (bitVectBitValue(sym->regsUsed,i)) {
3793 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3797 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3802 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3804 if (sym->stack == 1) {
3805 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3806 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3808 // we have to add more than one...
3809 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3810 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3811 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3813 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3814 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3815 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3819 if(strcmp(sym->name, "main")) {
3821 || !options.ommitFramePtr
3823 || IFFUNC_ARGS(sym->type)
3824 || FUNC_HASSTACKPARM(sym->etype)
3826 /* restore stack frame */
3827 if(STACK_MODEL_LARGE)
3828 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3829 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3835 if (IFFUNC_ISISR(sym->type)) {
3836 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3837 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3838 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3839 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3841 if(!FUNC_ISSHADOWREGS(sym->type)) {
3842 /* do not restore interrupt vector for WREG,STATUS,BSR
3843 * for high priority interrupt, see genFunction */
3844 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3845 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3846 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3848 // _G.interruptvector = 0; /* sanity check */
3851 /* if debug then send end of function */
3852 /* if (options.debug && currFunc) */
3854 debugFile->writeEndFunction (currFunc, ic, 1);
3857 if(_G.usefastretfie)
3858 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3860 pic16_emitpcodeNULLop(POC_RETFIE);
3862 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3864 _G.usefastretfie = 0;
3868 if (IFFUNC_ISCRITICAL(sym->type)) {
3869 pic16_emitcode("setb","ea");
3872 /* if debug then send end of function */
3874 debugFile->writeEndFunction (currFunc, ic, 1);
3877 /* insert code to restore stack frame, if user enabled it
3878 * and function is not main() */
3881 pic16_emitpcodeNULLop(POC_RETURN);
3883 /* Mark the end of a function */
3884 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3888 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3890 unsigned long lit=1;
3895 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3896 if(AOP_TYPE(op) == AOP_LIT) {
3897 if(!IS_FLOAT(operandType( op ))) {
3898 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3901 unsigned long lit_int;
3905 /* take care if literal is a float */
3906 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3912 if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
3913 pic16_emitpcode(POC_CLRF, dest);
3915 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3916 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3919 if(dest->type == PO_WREG && (offset == 0)) {
3920 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3923 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3927 /*-----------------------------------------------------------------*/
3928 /* genRet - generate code for return statement */
3929 /*-----------------------------------------------------------------*/
3930 static void genRet (iCode *ic)
3936 /* if we have no return value then
3937 * just generate the "ret" */
3942 /* we have something to return then
3943 * move the return value into place */
3944 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3945 size = AOP_SIZE(IC_LEFT(ic));
3949 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3952 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3955 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3957 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3960 /* >32-bits, setup stack and FSR0 */
3962 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3963 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3965 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3967 // popaopidx(AOP(oper), size, GpseudoStkPtr);
3972 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3973 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3975 if(STACK_MODEL_LARGE) {
3976 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3977 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3979 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3984 /* old code, left here for reference -- VR */
3988 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3990 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3991 pic16_emitpcomment("push %s",l);
3994 DEBUGpic16_emitcode(";", "%d", __LINE__);
3995 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3996 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
3998 if (strcmp(fReturn[offset],l)) {
3999 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4000 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4001 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4003 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4007 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4017 if (strcmp(fReturn[pushed],"a"))
4018 pic16_emitcode("pop",fReturn[pushed]);
4020 pic16_emitcode("pop","acc");
4026 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4029 /* generate a jump to the return label
4030 * if the next is not the return statement */
4031 if (!(ic->next && ic->next->op == LABEL
4032 && IC_LABEL(ic->next) == returnLabel)) {
4034 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4035 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4039 /*-----------------------------------------------------------------*/
4040 /* genLabel - generates a label */
4041 /*-----------------------------------------------------------------*/
4042 static void genLabel (iCode *ic)
4046 /* special case never generate */
4047 if (IC_LABEL(ic) == entryLabel)
4050 pic16_emitpLabel(IC_LABEL(ic)->key);
4051 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4054 /*-----------------------------------------------------------------*/
4055 /* genGoto - generates a goto */
4056 /*-----------------------------------------------------------------*/
4058 static void genGoto (iCode *ic)
4061 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4062 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4066 /*-----------------------------------------------------------------*/
4067 /* genMultbits :- multiplication of bits */
4068 /*-----------------------------------------------------------------*/
4069 static void genMultbits (operand *left,
4075 if(!pic16_sameRegs(AOP(result),AOP(right)))
4076 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4078 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4079 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4080 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4085 /*-----------------------------------------------------------------*/
4086 /* genMultOneByte : 8 bit multiplication & division */
4087 /*-----------------------------------------------------------------*/
4088 static void genMultOneByte (operand *left,
4094 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4095 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4097 /* (if two literals, the value is computed before) */
4098 /* if one literal, literal on the right */
4099 if (AOP_TYPE(left) == AOP_LIT){
4105 /* size is already checked in genMult == 1 */
4106 // size = AOP_SIZE(result);
4108 if (AOP_TYPE(right) == AOP_LIT){
4109 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4110 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4111 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4112 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4114 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4115 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4116 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4117 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4120 pic16_genMult8X8_8 (left, right,result);
4123 /*-----------------------------------------------------------------*/
4124 /* genMultOneWord : 16 bit multiplication */
4125 /*-----------------------------------------------------------------*/
4126 static void genMultOneWord (operand *left,
4131 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4132 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4134 /* (if two literals, the value is computed before)
4135 * if one literal, literal on the right */
4136 if (AOP_TYPE(left) == AOP_LIT){
4142 /* size is checked already == 2 */
4143 // size = AOP_SIZE(result);
4145 if (AOP_TYPE(right) == AOP_LIT) {
4146 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4147 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4148 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4149 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4151 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4152 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4153 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4154 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4157 pic16_genMult16X16_16(left, right,result);
4160 /*-----------------------------------------------------------------*/
4161 /* genMultOneLong : 32 bit multiplication */
4162 /*-----------------------------------------------------------------*/
4163 static void genMultOneLong (operand *left,
4168 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4169 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4171 /* (if two literals, the value is computed before)
4172 * if one literal, literal on the right */
4173 if (AOP_TYPE(left) == AOP_LIT){
4179 /* size is checked already == 4 */
4180 // size = AOP_SIZE(result);
4182 if (AOP_TYPE(right) == AOP_LIT) {
4183 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4184 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4185 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4186 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4188 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4189 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4190 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4191 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4194 pic16_genMult32X32_32(left, right,result);
4199 /*-----------------------------------------------------------------*/
4200 /* genMult - generates code for multiplication */
4201 /*-----------------------------------------------------------------*/
4202 static void genMult (iCode *ic)
4204 operand *left = IC_LEFT(ic);
4205 operand *right = IC_RIGHT(ic);
4206 operand *result= IC_RESULT(ic);
4209 /* assign the amsops */
4210 pic16_aopOp (left,ic,FALSE);
4211 pic16_aopOp (right,ic,FALSE);
4212 pic16_aopOp (result,ic,TRUE);
4214 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4216 /* special cases first *
4218 if (AOP_TYPE(left) == AOP_CRY
4219 && AOP_TYPE(right)== AOP_CRY) {
4220 genMultbits(left,right,result);
4224 /* if both are of size == 1 */
4225 if(AOP_SIZE(left) == 1
4226 && AOP_SIZE(right) == 1) {
4227 genMultOneByte(left,right,result);
4231 /* if both are of size == 2 */
4232 if(AOP_SIZE(left) == 2
4233 && AOP_SIZE(right) == 2) {
4234 genMultOneWord(left, right, result);
4238 /* if both are of size == 4 */
4239 if(AOP_SIZE(left) == 4
4240 && AOP_SIZE(right) == 4) {
4241 genMultOneLong(left, right, result);
4245 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4248 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4249 /* should have been converted to function call */
4253 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4254 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4255 pic16_freeAsmop(result,NULL,ic,TRUE);
4258 /*-----------------------------------------------------------------*/
4259 /* genDivbits :- division of bits */
4260 /*-----------------------------------------------------------------*/
4261 static void genDivbits (operand *left,
4268 /* the result must be bit */
4269 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4270 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4274 pic16_emitcode("div","ab");
4275 pic16_emitcode("rrc","a");
4276 pic16_aopPut(AOP(result),"c",0);
4279 /*-----------------------------------------------------------------*/
4280 /* genDivOneByte : 8 bit division */
4281 /*-----------------------------------------------------------------*/
4282 static void genDivOneByte (operand *left,
4286 sym_link *opetype = operandType(result);
4291 /* result = divident / divisor
4292 * - divident may be a register or a literal,
4293 * - divisor may be a register or a literal,
4294 * so there are 3 cases (literal / literal is optimized
4295 * by the front-end) to handle.
4296 * In addition we must handle signed and unsigned, which
4297 * result in 6 final different cases -- VR */
4301 size = AOP_SIZE(result) - 1;
4303 /* signed or unsigned */
4304 if (SPEC_USIGN(opetype)) {
4305 pCodeOp *pct1, /* count */
4308 symbol *label1, *label2, *label3;;
4311 /* unsigned is easy */
4313 pct1 = pic16_popGetTempReg(1);
4314 pct2 = pic16_popGetTempReg(1);
4315 pct3 = pic16_popGetTempReg(1);
4317 label1 = newiTempLabel(NULL);
4318 label2 = newiTempLabel(NULL);
4319 label3 = newiTempLabel(NULL);
4321 /* the following algorithm is extracted from divuint.c */
4323 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4324 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4326 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4328 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4330 pic16_emitpLabel(label1->key);
4333 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4337 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4341 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4343 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4344 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4346 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4347 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4348 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4350 pic16_emitpLabel( label3->key );
4351 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4352 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4356 pic16_emitpLabel(label2->key);
4357 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4358 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4359 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4361 /* result is in wreg */
4362 if(AOP_TYPE(result) != AOP_ACC)
4363 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4365 pic16_popReleaseTempReg( pct3, 1);
4366 pic16_popReleaseTempReg( pct2, 1);
4367 pic16_popReleaseTempReg( pct1, 1);
4372 /* signed is a little bit more difficult */
4374 /* save the signs of the operands */
4375 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4377 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4378 pic16_emitcode("push","acc"); /* save it on the stack */
4380 /* now sign adjust for both left & right */
4381 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4383 lbl = newiTempLabel(NULL);
4384 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4385 pic16_emitcode("cpl","a");
4386 pic16_emitcode("inc","a");
4387 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4388 pic16_emitcode("mov","b,a");
4390 /* sign adjust left side */
4391 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4394 lbl = newiTempLabel(NULL);
4395 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4396 pic16_emitcode("cpl","a");
4397 pic16_emitcode("inc","a");
4398 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4400 /* now the division */
4401 pic16_emitcode("div","ab");
4402 /* we are interested in the lower order
4404 pic16_emitcode("mov","b,a");
4405 lbl = newiTempLabel(NULL);
4406 pic16_emitcode("pop","acc");
4407 /* if there was an over flow we don't
4408 adjust the sign of the result */
4409 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4410 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4412 pic16_emitcode("clr","a");
4413 pic16_emitcode("subb","a,b");
4414 pic16_emitcode("mov","b,a");
4415 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4417 /* now we are done */
4418 pic16_aopPut(AOP(result),"b",0);
4420 pic16_emitcode("mov","c,b.7");
4421 pic16_emitcode("subb","a,acc");
4424 pic16_aopPut(AOP(result),"a",offset++);
4428 /*-----------------------------------------------------------------*/
4429 /* genDiv - generates code for division */
4430 /*-----------------------------------------------------------------*/
4431 static void genDiv (iCode *ic)
4433 operand *left = IC_LEFT(ic);
4434 operand *right = IC_RIGHT(ic);
4435 operand *result= IC_RESULT(ic);
4438 /* Division is a very lengthy algorithm, so it is better
4439 * to call support routines than inlining algorithm.
4440 * Division functions written here just in case someone
4441 * wants to inline and not use the support libraries -- VR */
4445 /* assign the amsops */
4446 pic16_aopOp (left,ic,FALSE);
4447 pic16_aopOp (right,ic,FALSE);
4448 pic16_aopOp (result,ic,TRUE);
4450 /* special cases first */
4452 if (AOP_TYPE(left) == AOP_CRY &&
4453 AOP_TYPE(right)== AOP_CRY) {
4454 genDivbits(left,right,result);
4458 /* if both are of size == 1 */
4459 if (AOP_SIZE(left) == 1 &&
4460 AOP_SIZE(right) == 1 ) {
4461 genDivOneByte(left,right,result);
4465 /* should have been converted to function call */
4468 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4469 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4470 pic16_freeAsmop(result,NULL,ic,TRUE);
4473 /*-----------------------------------------------------------------*/
4474 /* genModbits :- modulus of bits */
4475 /*-----------------------------------------------------------------*/
4476 static void genModbits (operand *left,
4484 werror(W_POSSBUG2, __FILE__, __LINE__);
4485 /* the result must be bit */
4486 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4487 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4491 pic16_emitcode("div","ab");
4492 pic16_emitcode("mov","a,b");
4493 pic16_emitcode("rrc","a");
4494 pic16_aopPut(AOP(result),"c",0);
4497 /*-----------------------------------------------------------------*/
4498 /* genModOneByte : 8 bit modulus */
4499 /*-----------------------------------------------------------------*/
4500 static void genModOneByte (operand *left,
4504 sym_link *opetype = operandType(result);
4509 werror(W_POSSBUG2, __FILE__, __LINE__);
4511 /* signed or unsigned */
4512 if (SPEC_USIGN(opetype)) {
4513 /* unsigned is easy */
4514 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4515 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4517 pic16_emitcode("div","ab");
4518 pic16_aopPut(AOP(result),"b",0);
4522 /* signed is a little bit more difficult */
4524 /* save the signs of the operands */
4525 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4528 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4529 pic16_emitcode("push","acc"); /* save it on the stack */
4531 /* now sign adjust for both left & right */
4532 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4535 lbl = newiTempLabel(NULL);
4536 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4537 pic16_emitcode("cpl","a");
4538 pic16_emitcode("inc","a");
4539 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4540 pic16_emitcode("mov","b,a");
4542 /* sign adjust left side */
4543 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4546 lbl = newiTempLabel(NULL);
4547 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4548 pic16_emitcode("cpl","a");
4549 pic16_emitcode("inc","a");
4550 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4552 /* now the multiplication */
4553 pic16_emitcode("div","ab");
4554 /* we are interested in the lower order
4556 lbl = newiTempLabel(NULL);
4557 pic16_emitcode("pop","acc");
4558 /* if there was an over flow we don't
4559 adjust the sign of the result */
4560 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4561 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4563 pic16_emitcode("clr","a");
4564 pic16_emitcode("subb","a,b");
4565 pic16_emitcode("mov","b,a");
4566 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4568 /* now we are done */
4569 pic16_aopPut(AOP(result),"b",0);
4573 /*-----------------------------------------------------------------*/
4574 /* genMod - generates code for division */
4575 /*-----------------------------------------------------------------*/
4576 static void genMod (iCode *ic)
4578 operand *left = IC_LEFT(ic);
4579 operand *right = IC_RIGHT(ic);
4580 operand *result= IC_RESULT(ic);
4584 /* assign the amsops */
4585 pic16_aopOp (left,ic,FALSE);
4586 pic16_aopOp (right,ic,FALSE);
4587 pic16_aopOp (result,ic,TRUE);
4589 /* special cases first */
4591 if (AOP_TYPE(left) == AOP_CRY &&
4592 AOP_TYPE(right)== AOP_CRY) {
4593 genModbits(left,right,result);
4597 /* if both are of size == 1 */
4598 if (AOP_SIZE(left) == 1 &&
4599 AOP_SIZE(right) == 1 ) {
4600 genModOneByte(left,right,result);
4604 /* should have been converted to function call */
4608 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4609 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4610 pic16_freeAsmop(result,NULL,ic,TRUE);
4613 /*-----------------------------------------------------------------*/
4614 /* genIfxJump :- will create a jump depending on the ifx */
4615 /*-----------------------------------------------------------------*/
4617 note: May need to add parameter to indicate when a variable is in bit space.
4619 static void genIfxJump (iCode *ic, char *jval)
4623 /* if true label then we jump if condition
4625 if ( IC_TRUE(ic) ) {
4627 if(strcmp(jval,"a") == 0)
4629 else if (strcmp(jval,"c") == 0)
4632 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4633 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4636 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4637 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4641 /* false label is present */
4642 if(strcmp(jval,"a") == 0)
4644 else if (strcmp(jval,"c") == 0)
4647 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4648 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4651 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4652 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4657 /* mark the icode as generated */
4661 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4665 /* if true label then we jump if condition
4667 if ( IC_TRUE(ic) ) {
4668 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4669 pic16_emitpcode(POC_BTFSC, jop);
4671 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4672 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4675 /* false label is present */
4676 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4677 pic16_emitpcode(POC_BTFSS, jop);
4679 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4680 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4684 /* mark the icode as generated */
4691 /*-----------------------------------------------------------------*/
4693 /*-----------------------------------------------------------------*/
4694 static void genSkip(iCode *ifx,int status_bit)
4696 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4700 if ( IC_TRUE(ifx) ) {
4701 switch(status_bit) {
4716 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4717 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4721 switch(status_bit) {
4735 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4736 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4743 /*-----------------------------------------------------------------*/
4745 /*-----------------------------------------------------------------*/
4746 static void genSkipc(resolvedIfx *rifx)
4748 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4758 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4759 rifx->generated = 1;
4762 #if !(USE_SIMPLE_GENCMP)
4763 /*-----------------------------------------------------------------*/
4765 /*-----------------------------------------------------------------*/
4766 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4768 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4773 if( (rifx->condition ^ invert_condition) & 1)
4778 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4779 rifx->generated = 1;
4784 /*-----------------------------------------------------------------*/
4786 /*-----------------------------------------------------------------*/
4787 static void genSkipz(iCode *ifx, int condition)
4798 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4800 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4803 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4805 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4810 #if !(USE_SIMPLE_GENCMP)
4811 /*-----------------------------------------------------------------*/
4813 /*-----------------------------------------------------------------*/
4814 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4820 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4822 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4825 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4826 rifx->generated = 1;
4831 /*-----------------------------------------------------------------*/
4832 /* genChkZeroes :- greater or less than comparison */
4833 /* For each byte in a literal that is zero, inclusive or the */
4834 /* the corresponding byte in the operand with W */
4835 /* returns true if any of the bytes are zero */
4836 /*-----------------------------------------------------------------*/
4837 static int genChkZeroes(operand *op, int lit, int size)
4844 i = (lit >> (size*8)) & 0xff;
4848 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4850 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4860 /*-----------------------------------------------------------------*/
4861 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4862 /* aop (if it's NOT a literal) or from lit (if */
4863 /* aop is a literal) */
4864 /*-----------------------------------------------------------------*/
4865 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4866 if (aop->type == AOP_LIT) {
4867 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4869 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4873 /*-----------------------------------------------------------------*/
4874 /* genCmp :- greater or less than comparison */
4875 /*-----------------------------------------------------------------*/
4877 #if USE_SIMPLE_GENCMP /* { */
4879 /* genCmp performs a left < right comparison, stores
4880 * the outcome in result (if != NULL) and generates
4881 * control flow code for the ifx (if != NULL).
4883 * This version leaves in sequences like
4884 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4885 * which should be optmized by the peephole
4886 * optimizer - RN 2005-01-01 */
4887 static void genCmp (operand *left,operand *right,
4888 operand *result, iCode *ifx, int sign)
4901 assert (left && right);
4902 assert (AOP_SIZE(left) == AOP_SIZE(right));
4904 size = AOP_SIZE(right) - 1;
4905 mask = (0x100UL << (size*8)) - 1;
4906 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4911 resolveIfx (&rIfx, ifx);
4913 /* handle for special cases */
4914 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4917 /**********************************************************************
4918 * handle bits - bit compares are promoted to int compares seemingly! *
4919 **********************************************************************/
4921 // THIS IS COMPLETELY UNTESTED!
4922 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4923 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4924 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4925 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4928 // 1 < {0,1} is false --> clear C by skipping the next instruction
4929 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4930 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4931 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4932 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4933 emitCLRC; // only skipped for left=0 && right=1
4935 goto correct_result_in_carry;
4939 /*************************************************
4940 * make sure that left is register (or the like) *
4941 *************************************************/
4942 if (!isAOP_REGlike(left)) {
4943 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4944 assert (isAOP_LIT(left));
4945 assert (isAOP_REGlike(right));
4946 // swap left and right
4947 // left < right <==> right > left <==> (right >= left + 1)
4948 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4950 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4951 // MAXVALUE < right? always false
4952 if (performedLt) emitCLRC; else emitSETC;
4953 goto correct_result_in_carry;
4956 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4957 // that's why we handled it above.
4964 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4965 } else if (isAOP_LIT(right)) {
4966 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4969 assert (isAOP_REGlike(left)); // left must be register or the like
4970 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4972 /*************************************************
4973 * special cases go here *
4974 *************************************************/
4976 if (isAOP_LIT(right)) {
4978 // unsigned comparison to a literal
4979 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4981 // unsigned left < 0? always false
4982 if (performedLt) emitCLRC; else emitSETC;
4983 goto correct_result_in_carry;
4986 // signed comparison to a literal
4987 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4988 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4989 // signed left < 0x80000000? always false
4990 if (performedLt) emitCLRC; else emitSETC;
4991 goto correct_result_in_carry;
4992 } else if (lit == 0) {
4993 // compare left < 0; set CARRY if SIGNBIT(left) is set
4994 if (performedLt) emitSETC; else emitCLRC;
4995 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4996 if (performedLt) emitCLRC; else emitSETC;
4997 goto correct_result_in_carry;
5000 } // right is literal
5002 /*************************************************
5003 * perform a general case comparison *
5004 * make sure we get CARRY==1 <==> left >= right *
5005 *************************************************/
5006 // compare most significant bytes
5007 //DEBUGpc ("comparing bytes at offset %d", size);
5009 // unsigned comparison
5010 mov2w_regOrLit (AOP(right), lit, size);
5011 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5013 // signed comparison
5014 // (add 2^n to both operands then perform an unsigned comparison)
5015 if (isAOP_LIT(right)) {
5016 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5017 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5019 if (litbyte == 0x80) {
5020 // left >= 0x80 -- always true, but more bytes to come
5021 pic16_mov2w (AOP(left), size);
5022 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5025 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5026 pic16_mov2w (AOP(left), size);
5027 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5028 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5031 /* using PRODL as a temporary register here */
5032 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5033 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5034 pic16_mov2w (AOP(left), size);
5035 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5036 pic16_emitpcode (POC_MOVWF, pctemp);
5037 pic16_mov2w (AOP(right), size);
5038 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5039 pic16_emitpcode (POC_SUBFW, pctemp);
5040 //pic16_popReleaseTempReg(pctemp, 1);
5044 // compare remaining bytes (treat as unsigned case from above)
5045 templbl = newiTempLabel ( NULL );
5048 //DEBUGpc ("comparing bytes at offset %d", offs);
5049 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5050 mov2w_regOrLit (AOP(right), lit, offs);
5051 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5053 pic16_emitpLabel (templbl->key);
5054 goto result_in_carry;
5058 /****************************************************
5059 * now CARRY contains the result of the comparison: *
5060 * SUBWF sets CARRY iff *
5061 * F-W >= 0 <==> F >= W <==> !(F < W) *
5062 * (F=left, W=right) *
5063 ****************************************************/
5066 if (result && AOP_TYPE(result) != AOP_CRY) {
5067 // value will be stored
5070 // value wil only be used in the following genSkipc()
5071 rIfx.condition ^= 1;
5075 correct_result_in_carry:
5077 // assign result to variable (if neccessary)
5078 if (result && AOP_TYPE(result) != AOP_CRY) {
5079 //DEBUGpc ("assign result");
5080 size = AOP_SIZE(result);
5082 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5084 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5087 // perform conditional jump
5089 //DEBUGpc ("generate control flow");
5098 static void genCmp (operand *left,operand *right,
5099 operand *result, iCode *ifx, int sign)
5101 int size; //, offset = 0 ;
5102 unsigned long lit = 0L,i = 0;
5103 resolvedIfx rFalseIfx;
5104 // resolvedIfx rTrueIfx;
5106 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5109 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5110 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5116 resolveIfx(&rFalseIfx,ifx);
5117 truelbl = newiTempLabel(NULL);
5118 size = max(AOP_SIZE(left),AOP_SIZE(right));
5120 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5124 /* if literal is on the right then swap with left */
5125 if ((AOP_TYPE(right) == AOP_LIT)) {
5126 operand *tmp = right ;
5127 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5128 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5131 lit = (lit - 1) & mask;
5134 rFalseIfx.condition ^= 1;
5137 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5138 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5142 //if(IC_TRUE(ifx) == NULL)
5143 /* if left & right are bit variables */
5144 if (AOP_TYPE(left) == AOP_CRY &&
5145 AOP_TYPE(right) == AOP_CRY ) {
5146 assert (0 && "bit variables used in genCmp");
5147 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5148 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5150 /* subtract right from left if at the
5151 end the carry flag is set then we know that
5152 left is greater than right */
5154 symbol *lbl = newiTempLabel(NULL);
5157 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5158 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5162 if(AOP_TYPE(right) == AOP_LIT) {
5164 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5166 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5173 genSkipCond(&rFalseIfx,left,size-1,7);
5175 /* no need to compare to 0...*/
5176 /* NOTE: this is a de-generate compare that most certainly
5177 * creates some dead code. */
5178 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5180 if(ifx) ifx->generated = 1;
5187 //i = (lit >> (size*8)) & 0xff;
5188 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5190 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5192 i = ((0-lit) & 0xff);
5195 /* lit is 0x7f, all signed chars are less than
5196 * this except for 0x7f itself */
5197 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5198 genSkipz2(&rFalseIfx,0);
5200 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5201 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5202 genSkipc(&rFalseIfx);
5207 genSkipz2(&rFalseIfx,1);
5209 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5210 genSkipc(&rFalseIfx);
5214 if(ifx) ifx->generated = 1;
5218 /* chars are out of the way. now do ints and longs */
5221 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5228 genSkipCond(&rFalseIfx,left,size,7);
5229 if(ifx) ifx->generated = 1;
5234 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5236 //rFalseIfx.condition ^= 1;
5237 //genSkipCond(&rFalseIfx,left,size,7);
5238 //rFalseIfx.condition ^= 1;
5240 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5241 if(rFalseIfx.condition)
5242 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5244 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5246 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5247 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5248 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5251 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5253 if(rFalseIfx.condition) {
5255 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5261 genSkipc(&rFalseIfx);
5262 pic16_emitpLabel(truelbl->key);
5263 if(ifx) ifx->generated = 1;
5270 if( (lit & 0xff) == 0) {
5271 /* lower byte is zero */
5272 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5273 i = ((lit >> 8) & 0xff) ^0x80;
5274 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5275 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5276 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5277 genSkipc(&rFalseIfx);
5280 if(ifx) ifx->generated = 1;
5285 /* Special cases for signed longs */
5286 if( (lit & 0xffffff) == 0) {
5287 /* lower byte is zero */
5288 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5289 i = ((lit >> 8*3) & 0xff) ^0x80;
5290 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5291 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5292 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5293 genSkipc(&rFalseIfx);
5296 if(ifx) ifx->generated = 1;
5304 if(lit & (0x80 << (size*8))) {
5305 /* lit is negative */
5306 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5308 //genSkipCond(&rFalseIfx,left,size,7);
5310 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5312 if(rFalseIfx.condition)
5313 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5315 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5319 /* lit is positive */
5320 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5321 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5322 if(rFalseIfx.condition)
5323 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5325 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5330 This works, but is only good for ints.
5331 It also requires a "known zero" register.
5332 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5333 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5334 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5335 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5336 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5337 genSkipc(&rFalseIfx);
5339 pic16_emitpLabel(truelbl->key);
5340 if(ifx) ifx->generated = 1;
5344 /* There are no more special cases, so perform a general compare */
5346 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5347 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5351 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5353 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5355 //rFalseIfx.condition ^= 1;
5356 genSkipc(&rFalseIfx);
5358 pic16_emitpLabel(truelbl->key);
5360 if(ifx) ifx->generated = 1;
5367 /* sign is out of the way. So now do an unsigned compare */
5368 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5371 /* General case - compare to an unsigned literal on the right.*/
5373 i = (lit >> (size*8)) & 0xff;
5374 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5375 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5377 i = (lit >> (size*8)) & 0xff;
5380 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5382 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5384 /* this byte of the lit is zero,
5385 *if it's not the last then OR in the variable */
5387 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5392 pic16_emitpLabel(lbl->key);
5393 // pic16_emitpLabel(truelbl->key);
5394 //if(emitFinalCheck)
5395 genSkipc(&rFalseIfx);
5397 pic16_emitpLabel(truelbl->key);
5399 if(ifx) ifx->generated = 1;
5406 if(AOP_TYPE(left) == AOP_LIT) {
5407 //symbol *lbl = newiTempLabel(NULL);
5409 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5412 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5415 if((lit == 0) && (sign == 0)){
5418 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5420 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5422 genSkipz2(&rFalseIfx,0);
5423 if(ifx) ifx->generated = 1;
5430 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5431 /* degenerate compare can never be true */
5432 if(rFalseIfx.condition == 0)
5433 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5435 if(ifx) ifx->generated = 1;
5440 /* signed comparisons to a literal byte */
5442 int lp1 = (lit+1) & 0xff;
5444 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5447 rFalseIfx.condition ^= 1;
5448 genSkipCond(&rFalseIfx,right,0,7);
5451 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5452 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5453 genSkipz2(&rFalseIfx,1);
5456 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5457 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5458 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5459 rFalseIfx.condition ^= 1;
5460 genSkipc(&rFalseIfx);
5464 /* unsigned comparisons to a literal byte */
5466 switch(lit & 0xff ) {
5468 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5469 genSkipz2(&rFalseIfx,0);
5472 rFalseIfx.condition ^= 1;
5473 genSkipCond(&rFalseIfx,right,0,7);
5477 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5478 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5479 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5480 rFalseIfx.condition ^= 1;
5481 if (AOP_TYPE(result) == AOP_CRY)
5482 genSkipc(&rFalseIfx);
5484 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5485 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5491 if(ifx) ifx->generated = 1;
5492 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5498 /* Size is greater than 1 */
5506 /* this means lit = 0xffffffff, or -1 */
5509 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5510 rFalseIfx.condition ^= 1;
5511 genSkipCond(&rFalseIfx,right,size,7);
5512 if(ifx) ifx->generated = 1;
5514 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5523 if(rFalseIfx.condition) {
5524 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5525 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5528 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5530 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5534 if(rFalseIfx.condition) {
5535 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5536 pic16_emitpLabel(truelbl->key);
5538 rFalseIfx.condition ^= 1;
5539 genSkipCond(&rFalseIfx,right,s,7);
5542 if(ifx) ifx->generated = 1;
5544 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5550 if((size == 1) && (0 == (lp1&0xff))) {
5551 /* lower byte of signed word is zero */
5552 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5553 i = ((lp1 >> 8) & 0xff) ^0x80;
5554 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5555 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5556 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5558 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5560 if(ifx) ifx->generated = 1;
5563 rFalseIfx.condition ^= 1;
5564 genSkipc(&rFalseIfx);
5565 if(ifx) ifx->generated = 1;
5571 if(lit & (0x80 << (size*8))) {
5572 /* Lit is less than zero */
5573 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5574 //rFalseIfx.condition ^= 1;
5575 //genSkipCond(&rFalseIfx,left,size,7);
5576 //rFalseIfx.condition ^= 1;
5577 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5578 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5580 if(rFalseIfx.condition)
5581 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5583 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5587 /* Lit is greater than or equal to zero */
5588 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5589 //rFalseIfx.condition ^= 1;
5590 //genSkipCond(&rFalseIfx,right,size,7);
5591 //rFalseIfx.condition ^= 1;
5593 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5594 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5596 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5597 if(rFalseIfx.condition)
5598 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5600 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5604 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5605 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5609 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5611 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5613 rFalseIfx.condition ^= 1;
5614 //rFalseIfx.condition = 1;
5615 genSkipc(&rFalseIfx);
5617 pic16_emitpLabel(truelbl->key);
5619 if(ifx) ifx->generated = 1;
5622 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5629 /* compare word or long to an unsigned literal on the right.*/
5634 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5637 break; /* handled above */
5640 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5642 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5643 genSkipz2(&rFalseIfx,0);
5647 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5649 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5652 if(rFalseIfx.condition)
5653 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5655 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5658 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5659 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5661 rFalseIfx.condition ^= 1;
5662 genSkipc(&rFalseIfx);
5665 pic16_emitpLabel(truelbl->key);
5667 if(ifx) ifx->generated = 1;
5669 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5677 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5678 i = (lit >> (size*8)) & 0xff;
5680 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5681 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5684 i = (lit >> (size*8)) & 0xff;
5687 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5689 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5691 /* this byte of the lit is zero,
5692 * if it's not the last then OR in the variable */
5694 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5699 pic16_emitpLabel(lbl->key);
5701 rFalseIfx.condition ^= 1;
5703 genSkipc(&rFalseIfx);
5707 pic16_emitpLabel(truelbl->key);
5708 if(ifx) ifx->generated = 1;
5710 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5716 /* Compare two variables */
5718 DEBUGpic16_emitcode(";sign","%d",sign);
5722 /* Sigh. thus sucks... */
5726 pctemp = pic16_popGetTempReg(1);
5727 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5728 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5729 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5730 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5731 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5732 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5733 pic16_popReleaseTempReg(pctemp, 1);
5735 /* Signed char comparison */
5736 /* Special thanks to Nikolai Golovchenko for this snippet */
5737 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5738 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5739 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5740 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5741 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5742 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5744 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5745 genSkipc(&rFalseIfx);
5747 if(ifx) ifx->generated = 1;
5749 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5757 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5758 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5762 /* The rest of the bytes of a multi-byte compare */
5766 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5769 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5770 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5775 pic16_emitpLabel(lbl->key);
5777 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5778 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5779 (AOP_TYPE(result) == AOP_REG)) {
5780 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5781 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5783 genSkipc(&rFalseIfx);
5785 //genSkipc(&rFalseIfx);
5786 if(ifx) ifx->generated = 1;
5789 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5797 if ((AOP_TYPE(result) != AOP_CRY)
5798 && AOP_SIZE(result)) {
5799 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5801 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5803 pic16_outBitC(result);
5805 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5806 /* if the result is used in the next
5807 ifx conditional branch then generate
5808 code a little differently */
5810 genIfxJump (ifx,"c");
5812 pic16_outBitC(result);
5813 /* leave the result in acc */
5818 #elif 0 /* VR version of genCmp() */ /* } else { */
5820 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5821 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5822 operand *result, int offset, int invert_op)
5826 /* check condition, > or < ?? */
5827 if(rIfx->condition != 0)invert_op ^= 1;
5829 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5831 if(!ifx)invert_op ^= 1;
5833 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5834 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5837 if(!invert_op)return POC_CPFSGT;
5838 else return POC_CPFSLT;
5841 static int compareAopfirstpass=1;
5843 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5844 operand *oper, int offset, operand *result,
5845 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5851 /* invert if there is a result to be loaded, in order to fit,
5852 * SETC/CLRC sequence */
5853 if(AOP_SIZE(result))invert_op ^= 1;
5855 // if(sign && !offset)invert_op ^= 1;
5857 // if(sign)invert_op ^= 1;
5859 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5861 if(AOP_SIZE(result) && compareAopfirstpass) {
5864 pic16_emitpcode(POC_SETF, pcop2);
5869 pic16_emitpcode(POC_CLRF, pcop2);
5875 compareAopfirstpass = 0;
5877 /* there is a bug when comparing operands with size > 1,
5878 * because higher bytes can be equal and test should be performed
5879 * to the next lower byte, current algorithm, considers operands
5880 * inequal in these cases! -- VR 20041107 */
5884 pic16_emitpcode(op, pcop);
5886 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5889 if((!sign || !offset) && AOP_SIZE(result)) {
5892 pic16_emitpcode(POC_CLRF, pcop2);
5897 pic16_emitpcode(POC_SETF, pcop2);
5902 /* don't emit final branch (offset == 0) */
5906 pic16_emitpcode(POC_RRCF, pcop2);
5908 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5911 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5912 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5913 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5915 truelbl = newiTempLabel( NULL );
5916 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5917 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5918 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5920 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5921 pic16_emitpLabel(truelbl->key);
5923 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5928 static void genCmp (operand *left, operand *right,
5929 operand *result, iCode *ifx, int sign)
5933 resolvedIfx rFalseIfx;
5934 symbol *falselbl, *tlbl;
5938 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5940 resolveIfx(&rFalseIfx, ifx);
5941 size = max(AOP_SIZE(left), AOP_SIZE(right));
5943 /* if left & right are bit variables */
5944 if(AOP_TYPE(left) == AOP_CRY
5945 && AOP_TYPE(right) == AOP_CRY ) {
5947 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5948 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5950 werror(W_POSSBUG2, __FILE__, __LINE__);
5954 /* if literal is on the right then swap with left */
5955 if((AOP_TYPE(right) == AOP_LIT)) {
5956 operand *tmp = right ;
5957 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
5959 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5961 // lit = (lit - 1) & mask;
5964 rFalseIfx.condition ^= 1; /* reverse compare */
5966 if ((AOP_TYPE(left) == AOP_LIT)) {
5967 /* float compares are handled by support functions */
5968 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5971 /* actual comparing algorithm */
5972 // size = AOP_SIZE( right );
5974 falselbl = newiTempLabel( NULL );
5975 if(AOP_TYPE(left) == AOP_LIT) {
5976 /* compare to literal */
5977 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5980 pCodeOp *pct, *pct2;
5983 /* signed compare */
5984 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5986 /* using PRODL:PRODH as a temporary register here */
5987 pct = pic16_popCopyReg(&pic16_pc_prodl);
5988 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5989 tlbl = newiTempLabel( NULL );
5991 /* first compare signs:
5992 * a. if both are positive, compare just like unsigned
5993 * b. if both are negative, invert cmpop, compare just like unsigned
5994 * c. if different signs, determine the result directly */
6000 tlbl1 = newiTempLabel( NULL );
6001 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6005 /* literal is zero or positive:
6006 * a. if carry is zero, too, continue compare,
6007 * b. if carry is set, then continue depending on cmpop ^ condition:
6008 * 1. '<' return false (literal < variable),
6009 * 2. '>' return true (literal > variable) */
6010 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6011 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6014 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6015 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6019 /* literal is negative:
6020 * a. if carry is set, too, continue compare,
6021 * b. if carry is zero, then continue depending on cmpop ^ condition:
6022 * 1. '<' return true (literal < variable),
6023 * 2. '>' return false (literal > variable) */
6024 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6025 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6027 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6028 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6033 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6035 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6036 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6041 pic16_emitpLabel( tlbl1->key );
6044 compareAopfirstpass=1;
6045 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6046 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6047 // pic16_emitpcode(POC_MOVWF, pct);
6049 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6050 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6051 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6052 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6056 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6057 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6058 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6059 // pic16_emitpcode(POC_MOVWF, pct);
6061 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6062 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6063 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6064 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6065 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6068 if(ifx)ifx->generated = 1;
6070 if(AOP_SIZE(result)) {
6071 pic16_emitpLabel(tlbl->key);
6072 pic16_emitpLabel(falselbl->key);
6073 pic16_outBitOp( result, pct2 );
6075 pic16_emitpLabel(tlbl->key);
6079 /* unsigned compare */
6080 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6082 compareAopfirstpass=1;
6085 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6086 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6089 if(ifx)ifx->generated = 1;
6091 if(AOP_SIZE(result)) {
6092 pic16_emitpLabel(falselbl->key);
6093 pic16_outBitC( result );
6098 /* compare registers */
6099 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6103 pCodeOp *pct, *pct2;
6105 /* signed compare */
6106 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6108 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6109 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6110 tlbl = newiTempLabel( NULL );
6112 compareAopfirstpass=1;
6115 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6116 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6117 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6118 pic16_emitpcode(POC_MOVWF, pct);
6120 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6121 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6122 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6124 /* WREG already holds left + 0x80 */
6125 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6128 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6129 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6130 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6131 pic16_emitpcode(POC_MOVWF, pct);
6133 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6134 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6135 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6137 /* WREG already holds left + 0x80 */
6138 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6139 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6142 if(ifx)ifx->generated = 1;
6144 if(AOP_SIZE(result)) {
6145 pic16_emitpLabel(tlbl->key);
6146 pic16_emitpLabel(falselbl->key);
6147 pic16_outBitOp( result, pct2 );
6149 pic16_emitpLabel(tlbl->key);
6153 /* unsigned compare */
6154 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6156 compareAopfirstpass=1;
6159 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6160 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6164 if(ifx)ifx->generated = 1;
6165 if(AOP_SIZE(result)) {
6167 pic16_emitpLabel(falselbl->key);
6168 pic16_outBitC( result );
6179 /*-----------------------------------------------------------------*/
6180 /* genCmpGt :- greater than comparison */
6181 /*-----------------------------------------------------------------*/
6182 static void genCmpGt (iCode *ic, iCode *ifx)
6184 operand *left, *right, *result;
6185 sym_link *letype , *retype;
6191 right= IC_RIGHT(ic);
6192 result = IC_RESULT(ic);
6194 letype = getSpec(operandType(left));
6195 retype =getSpec(operandType(right));
6196 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6197 /* assign the amsops */
6198 pic16_aopOp (left,ic,FALSE);
6199 pic16_aopOp (right,ic,FALSE);
6200 pic16_aopOp (result,ic,TRUE);
6202 genCmp(right, left, result, ifx, sign);
6204 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6205 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6206 pic16_freeAsmop(result,NULL,ic,TRUE);
6209 /*-----------------------------------------------------------------*/
6210 /* genCmpLt - less than comparisons */
6211 /*-----------------------------------------------------------------*/
6212 static void genCmpLt (iCode *ic, iCode *ifx)
6214 operand *left, *right, *result;
6215 sym_link *letype , *retype;
6221 right= IC_RIGHT(ic);
6222 result = IC_RESULT(ic);
6224 letype = getSpec(operandType(left));
6225 retype =getSpec(operandType(right));
6226 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6228 /* assign the amsops */
6229 pic16_aopOp (left,ic,FALSE);
6230 pic16_aopOp (right,ic,FALSE);
6231 pic16_aopOp (result,ic,TRUE);
6233 genCmp(left, right, result, ifx, sign);
6235 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6236 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6237 pic16_freeAsmop(result,NULL,ic,TRUE);
6242 // FIXME reenable literal optimisation when the pic16 port is stable
6244 /*-----------------------------------------------------------------*/
6245 /* genc16bit2lit - compare a 16 bit value to a literal */
6246 /*-----------------------------------------------------------------*/
6247 static void genc16bit2lit(operand *op, int lit, int offset)
6251 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6252 if( (lit&0xff) == 0)
6257 switch( BYTEofLONG(lit,i)) {
6259 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6262 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6265 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6268 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6269 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6274 switch( BYTEofLONG(lit,i)) {
6276 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6280 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6284 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6287 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6289 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6298 /*-----------------------------------------------------------------*/
6299 /* gencjneshort - compare and jump if not equal */
6300 /*-----------------------------------------------------------------*/
6301 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6303 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6305 int res_offset = 0; /* the result may be a different size then left or right */
6306 int res_size = AOP_SIZE(result);
6308 symbol *lbl, *lbl_done;
6310 unsigned long lit = 0L;
6311 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6313 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6314 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6316 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6317 resolveIfx(&rIfx,ifx);
6318 lbl = newiTempLabel(NULL);
6319 lbl_done = newiTempLabel(NULL);
6322 /* if the left side is a literal or
6323 if the right is in a pointer register and left
6325 if ((AOP_TYPE(left) == AOP_LIT) ||
6326 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6331 if(AOP_TYPE(right) == AOP_LIT)
6332 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6334 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6335 preserve_result = 1;
6337 if(result && !preserve_result)
6340 for(i = 0; i < AOP_SIZE(result); i++)
6341 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6345 /* if the right side is a literal then anything goes */
6346 if (AOP_TYPE(right) == AOP_LIT &&
6347 AOP_TYPE(left) != AOP_DIR ) {
6350 genc16bit2lit(left, lit, 0);
6352 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6355 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6358 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6359 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6361 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6365 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6367 if(res_offset < res_size-1)
6375 /* if the right side is in a register or in direct space or
6376 if the left is a pointer register & right is not */
6377 else if (AOP_TYPE(right) == AOP_REG ||
6378 AOP_TYPE(right) == AOP_DIR ||
6379 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6380 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6381 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6382 int lbl_key = lbl->key;
6385 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6386 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6388 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6389 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6390 __FUNCTION__,__LINE__);
6394 /* switch(size) { */
6396 /* genc16bit2lit(left, lit, 0); */
6398 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6403 if((AOP_TYPE(left) == AOP_DIR) &&
6404 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6406 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6407 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6409 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6411 switch (lit & 0xff) {
6413 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6416 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6417 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6418 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6422 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6423 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6424 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6425 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6429 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6430 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6435 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6438 if(AOP_TYPE(result) == AOP_CRY) {
6439 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6444 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6446 /* fix me. probably need to check result size too */
6447 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6452 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6453 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6460 if(res_offset < res_size-1)
6465 } else if(AOP_TYPE(right) == AOP_REG &&
6466 AOP_TYPE(left) != AOP_DIR){
6469 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6470 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6471 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6476 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6478 if(res_offset < res_size-1)
6483 /* right is a pointer reg need both a & b */
6485 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6487 pic16_emitcode("mov","b,%s",l);
6488 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6489 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6494 if(result && preserve_result)
6497 for(i = 0; i < AOP_SIZE(result); i++)
6498 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6501 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6503 if(result && preserve_result)
6504 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6507 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6509 pic16_emitpLabel(lbl->key);
6511 if(result && preserve_result)
6514 for(i = 0; i < AOP_SIZE(result); i++)
6515 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6517 pic16_emitpLabel(lbl_done->key);
6520 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6528 /*-----------------------------------------------------------------*/
6529 /* gencjne - compare and jump if not equal */
6530 /*-----------------------------------------------------------------*/
6531 static void gencjne(operand *left, operand *right, iCode *ifx)
6533 symbol *tlbl = newiTempLabel(NULL);
6535 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6536 gencjneshort(left, right, lbl);
6538 pic16_emitcode("mov","a,%s",one);
6539 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6540 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6541 pic16_emitcode("clr","a");
6542 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6544 pic16_emitpLabel(lbl->key);
6545 pic16_emitpLabel(tlbl->key);
6551 /*-----------------------------------------------------------------*/
6552 /* is_LitOp - check if operand has to be treated as literal */
6553 /*-----------------------------------------------------------------*/
6554 static bool is_LitOp(operand *op)
6556 return ((AOP_TYPE(op) == AOP_LIT)
6557 || ( (AOP_TYPE(op) == AOP_PCODE)
6558 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6559 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6562 /*-----------------------------------------------------------------*/
6563 /* is_LitAOp - check if operand has to be treated as literal */
6564 /*-----------------------------------------------------------------*/
6565 static bool is_LitAOp(asmop *aop)
6567 return ((aop->type == AOP_LIT)
6568 || ( (aop->type == AOP_PCODE)
6569 && ( (aop->aopu.pcop->type == PO_LITERAL)
6570 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6575 /*-----------------------------------------------------------------*/
6576 /* genCmpEq - generates code for equal to */
6577 /*-----------------------------------------------------------------*/
6578 static void genCmpEq (iCode *ic, iCode *ifx)
6580 operand *left, *right, *result;
6581 symbol *falselbl = newiTempLabel(NULL);
6582 symbol *donelbl = newiTempLabel(NULL);
6584 int preserve_result = 0;
6585 int generate_result = 0;
6587 unsigned long lit = -1;
6591 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6592 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6593 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6595 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6597 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6599 werror(W_POSSBUG2, __FILE__, __LINE__);
6600 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6601 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6605 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6607 operand *tmp = right ;
6612 if (AOP_TYPE(right) == AOP_LIT) {
6613 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6616 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6617 preserve_result = 1;
6619 if(result && AOP_SIZE(result))
6620 generate_result = 1;
6622 if(generate_result && !preserve_result)
6624 for(i = 0; i < AOP_SIZE(result); i++)
6625 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6628 assert( AOP_SIZE(left) == AOP_SIZE(right) );
6629 for(i=0; i < AOP_SIZE(left); i++)
6631 if(AOP_TYPE(left) != AOP_ACC)
6634 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6636 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6638 if(is_LitOp(right)) {
6639 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6640 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6643 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6645 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6650 if(generate_result && preserve_result)
6652 for(i = 0; i < AOP_SIZE(result); i++)
6653 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6657 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6659 if(generate_result && preserve_result)
6660 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6662 if(ifx && IC_TRUE(ifx))
6663 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6665 if(ifx && IC_FALSE(ifx))
6666 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6668 pic16_emitpLabel(falselbl->key);
6672 if(ifx && IC_FALSE(ifx))
6673 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6675 if(generate_result && preserve_result)
6677 for(i = 0; i < AOP_SIZE(result); i++)
6678 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6681 pic16_emitpLabel(donelbl->key);
6687 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6688 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6689 pic16_freeAsmop(result,NULL,ic,TRUE);
6695 // old version kept for reference
6697 /*-----------------------------------------------------------------*/
6698 /* genCmpEq - generates code for equal to */
6699 /*-----------------------------------------------------------------*/
6700 static void genCmpEq (iCode *ic, iCode *ifx)
6702 operand *left, *right, *result;
6703 unsigned long lit = 0L;
6705 symbol *falselbl = newiTempLabel(NULL);
6708 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6711 DEBUGpic16_emitcode ("; ifx is non-null","");
6713 DEBUGpic16_emitcode ("; ifx is null","");
6715 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6716 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6717 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6719 size = max(AOP_SIZE(left),AOP_SIZE(right));
6721 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6723 /* if literal, literal on the right or
6724 if the right is in a pointer register and left
6726 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6727 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6728 operand *tmp = right ;
6734 if(ifx && !AOP_SIZE(result)){
6736 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6737 /* if they are both bit variables */
6738 if (AOP_TYPE(left) == AOP_CRY &&
6739 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6740 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6741 if(AOP_TYPE(right) == AOP_LIT){
6742 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6744 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6745 pic16_emitcode("cpl","c");
6746 } else if(lit == 1L) {
6747 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6749 pic16_emitcode("clr","c");
6751 /* AOP_TYPE(right) == AOP_CRY */
6753 symbol *lbl = newiTempLabel(NULL);
6754 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6755 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6756 pic16_emitcode("cpl","c");
6757 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6759 /* if true label then we jump if condition
6761 tlbl = newiTempLabel(NULL);
6762 if ( IC_TRUE(ifx) ) {
6763 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6764 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6766 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6767 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6769 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6772 /* left and right are both bit variables, result is carry */
6775 resolveIfx(&rIfx,ifx);
6777 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6778 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6779 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6780 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6785 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6787 /* They're not both bit variables. Is the right a literal? */
6788 if(AOP_TYPE(right) == AOP_LIT) {
6789 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6794 switch(lit & 0xff) {
6796 if ( IC_TRUE(ifx) ) {
6797 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6799 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6801 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6802 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6806 if ( IC_TRUE(ifx) ) {
6807 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6809 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6811 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6812 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6816 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6818 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6823 /* end of size == 1 */
6827 genc16bit2lit(left,lit,offset);
6830 /* end of size == 2 */
6835 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6836 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6837 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6838 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6841 /* search for patterns that can be optimized */
6843 genc16bit2lit(left,lit,0);
6847 emitSKPZ; // if hi word unequal
6849 emitSKPNZ; // if hi word equal
6851 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6852 genc16bit2lit(left,lit,2);
6855 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6856 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6860 pic16_emitpLabel(falselbl->key);
6869 } else if(AOP_TYPE(right) == AOP_CRY ) {
6870 /* we know the left is not a bit, but that the right is */
6871 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6872 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6873 pic16_popGet(AOP(right),offset));
6874 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6876 /* if the two are equal, then W will be 0 and the Z bit is set
6877 * we could test Z now, or go ahead and check the high order bytes if
6878 * the variable we're comparing is larger than a byte. */
6881 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6883 if ( IC_TRUE(ifx) ) {
6885 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6886 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6889 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6890 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6894 /* They're both variables that are larger than bits */
6897 tlbl = newiTempLabel(NULL);
6900 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6901 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6903 if ( IC_TRUE(ifx) ) {
6907 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6909 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6910 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6914 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6917 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6918 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6923 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6925 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6926 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6930 if(s>1 && IC_TRUE(ifx)) {
6931 pic16_emitpLabel(tlbl->key);
6932 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6936 /* mark the icode as generated */
6941 /* if they are both bit variables */
6942 if (AOP_TYPE(left) == AOP_CRY &&
6943 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6944 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
6945 if(AOP_TYPE(right) == AOP_LIT){
6946 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6948 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6949 pic16_emitcode("cpl","c");
6950 } else if(lit == 1L) {
6951 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6953 pic16_emitcode("clr","c");
6955 /* AOP_TYPE(right) == AOP_CRY */
6957 symbol *lbl = newiTempLabel(NULL);
6958 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6959 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6960 pic16_emitcode("cpl","c");
6961 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6964 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6965 pic16_outBitC(result);
6969 genIfxJump (ifx,"c");
6972 /* if the result is used in an arithmetic operation
6973 then put the result in place */
6974 pic16_outBitC(result);
6977 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
6978 gencjne(left,right,result,ifx);
6981 gencjne(left,right,newiTempLabel(NULL));
6983 if(IC_TRUE(ifx)->key)
6984 gencjne(left,right,IC_TRUE(ifx)->key);
6986 gencjne(left,right,IC_FALSE(ifx)->key);
6990 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6991 pic16_aopPut(AOP(result),"a",0);
6996 genIfxJump (ifx,"a");
7000 /* if the result is used in an arithmetic operation
7001 then put the result in place */
7003 if (AOP_TYPE(result) != AOP_CRY)
7004 pic16_outAcc(result);
7006 /* leave the result in acc */
7010 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7011 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7012 pic16_freeAsmop(result,NULL,ic,TRUE);
7016 /*-----------------------------------------------------------------*/
7017 /* ifxForOp - returns the icode containing the ifx for operand */
7018 /*-----------------------------------------------------------------*/
7019 static iCode *ifxForOp ( operand *op, iCode *ic )
7023 /* if true symbol then needs to be assigned */
7024 if (IS_TRUE_SYMOP(op))
7027 /* if this has register type condition and
7028 the next instruction is ifx with the same operand
7029 and live to of the operand is upto the ifx only then */
7031 && ic->next->op == IFX
7032 && IC_COND(ic->next)->key == op->key
7033 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7035 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7041 ic->next->op == IFX &&
7042 IC_COND(ic->next)->key == op->key) {
7043 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7048 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7050 ic->next->op == IFX)
7051 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7054 ic->next->op == IFX &&
7055 IC_COND(ic->next)->key == op->key) {
7056 DEBUGpic16_emitcode ("; "," key is okay");
7057 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7058 OP_SYMBOL(op)->liveTo,
7063 /* the code below is completely untested
7064 * it just allows ulong2fs.c compile -- VR */
7067 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7068 __FILE__, __FUNCTION__, __LINE__);
7070 /* if this has register type condition and
7071 the next instruction is ifx with the same operand
7072 and live to of the operand is upto the ifx only then */
7074 ic->next->op == IFX &&
7075 IC_COND(ic->next)->key == op->key &&
7076 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7080 ic->next->op == IFX &&
7081 IC_COND(ic->next)->key == op->key) {
7082 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7086 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7087 __FILE__, __FUNCTION__, __LINE__);
7089 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7094 /*-----------------------------------------------------------------*/
7095 /* genAndOp - for && operation */
7096 /*-----------------------------------------------------------------*/
7097 static void genAndOp (iCode *ic)
7099 operand *left,*right, *result;
7104 /* note here that && operations that are in an
7105 if statement are taken away by backPatchLabels
7106 only those used in arthmetic operations remain */
7107 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7108 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7109 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7111 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7113 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7114 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7115 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7117 /* if both are bit variables */
7118 /* if (AOP_TYPE(left) == AOP_CRY && */
7119 /* AOP_TYPE(right) == AOP_CRY ) { */
7120 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7121 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7122 /* pic16_outBitC(result); */
7124 /* tlbl = newiTempLabel(NULL); */
7125 /* pic16_toBoolean(left); */
7126 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7127 /* pic16_toBoolean(right); */
7128 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7129 /* pic16_outBitAcc(result); */
7132 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7133 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7134 pic16_freeAsmop(result,NULL,ic,TRUE);
7138 /*-----------------------------------------------------------------*/
7139 /* genOrOp - for || operation */
7140 /*-----------------------------------------------------------------*/
7143 modified this code, but it doesn't appear to ever get called
7146 static void genOrOp (iCode *ic)
7148 operand *left,*right, *result;
7153 /* note here that || operations that are in an
7154 if statement are taken away by backPatchLabels
7155 only those used in arthmetic operations remain */
7156 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7157 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7158 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7160 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7162 /* if both are bit variables */
7163 if (AOP_TYPE(left) == AOP_CRY &&
7164 AOP_TYPE(right) == AOP_CRY ) {
7165 pic16_emitcode("clrc","");
7166 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7167 AOP(left)->aopu.aop_dir,
7168 AOP(left)->aopu.aop_dir);
7169 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7170 AOP(right)->aopu.aop_dir,
7171 AOP(right)->aopu.aop_dir);
7172 pic16_emitcode("setc","");
7175 tlbl = newiTempLabel(NULL);
7176 pic16_toBoolean(left);
7178 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7179 pic16_toBoolean(right);
7180 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7182 pic16_outBitAcc(result);
7185 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7186 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7187 pic16_freeAsmop(result,NULL,ic,TRUE);
7190 /*-----------------------------------------------------------------*/
7191 /* isLiteralBit - test if lit == 2^n */
7192 /*-----------------------------------------------------------------*/
7193 static int isLiteralBit(unsigned long lit)
7195 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7196 0x100L,0x200L,0x400L,0x800L,
7197 0x1000L,0x2000L,0x4000L,0x8000L,
7198 0x10000L,0x20000L,0x40000L,0x80000L,
7199 0x100000L,0x200000L,0x400000L,0x800000L,
7200 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7201 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7204 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7205 for(idx = 0; idx < 32; idx++)
7211 /*-----------------------------------------------------------------*/
7212 /* continueIfTrue - */
7213 /*-----------------------------------------------------------------*/
7214 static void continueIfTrue (iCode *ic)
7218 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7222 /*-----------------------------------------------------------------*/
7224 /*-----------------------------------------------------------------*/
7225 static void jumpIfTrue (iCode *ic)
7229 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7233 /*-----------------------------------------------------------------*/
7234 /* jmpTrueOrFalse - */
7235 /*-----------------------------------------------------------------*/
7236 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7238 // ugly but optimized by peephole
7241 symbol *nlbl = newiTempLabel(NULL);
7242 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7243 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7244 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7245 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7247 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7248 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7253 /*-----------------------------------------------------------------*/
7254 /* genAnd - code for and */
7255 /*-----------------------------------------------------------------*/
7256 static void genAnd (iCode *ic, iCode *ifx)
7258 operand *left, *right, *result;
7260 unsigned long lit = 0L;
7266 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7267 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7268 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7270 resolveIfx(&rIfx,ifx);
7272 /* if left is a literal & right is not then exchange them */
7273 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7274 AOP_NEEDSACC(left)) {
7275 operand *tmp = right ;
7280 /* if result = right then exchange them */
7281 if(pic16_sameRegs(AOP(result),AOP(right))){
7282 operand *tmp = right ;
7287 /* if right is bit then exchange them */
7288 if (AOP_TYPE(right) == AOP_CRY &&
7289 AOP_TYPE(left) != AOP_CRY){
7290 operand *tmp = right ;
7294 if(AOP_TYPE(right) == AOP_LIT)
7295 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7297 size = AOP_SIZE(result);
7299 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7302 // result = bit & yy;
7303 if (AOP_TYPE(left) == AOP_CRY){
7304 // c = bit & literal;
7305 if(AOP_TYPE(right) == AOP_LIT){
7307 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7310 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7313 if(size && (AOP_TYPE(result) == AOP_CRY)){
7314 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7317 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7321 pic16_emitcode("clr","c");
7324 if (AOP_TYPE(right) == AOP_CRY){
7326 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7327 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7330 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7332 pic16_emitcode("rrc","a");
7333 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7339 pic16_outBitC(result);
7341 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7342 genIfxJump(ifx, "c");
7346 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7347 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7348 if((AOP_TYPE(right) == AOP_LIT) &&
7349 (AOP_TYPE(result) == AOP_CRY) &&
7350 (AOP_TYPE(left) != AOP_CRY)){
7351 int posbit = isLiteralBit(lit);
7355 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7358 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7364 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7365 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7367 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7368 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7371 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7372 size = AOP_SIZE(left);
7375 int bp = posbit, ofs=0;
7382 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7383 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7387 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7388 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7390 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7397 symbol *tlbl = newiTempLabel(NULL);
7398 int sizel = AOP_SIZE(left);
7404 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7406 /* patch provided by Aaron Colwell */
7407 if((posbit = isLiteralBit(bytelit)) != 0) {
7408 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7409 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7410 (posbit-1),0, PO_GPR_REGISTER));
7412 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7413 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7415 if (bytelit == 0xff) {
7416 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7417 * a peephole could optimize it out -- VR */
7418 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7420 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7421 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7424 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7425 pic16_popGetLabel(tlbl->key));
7429 /* old code, left here for reference -- VR 09/2004 */
7430 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7432 if((posbit = isLiteralBit(bytelit)) != 0)
7433 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7435 if(bytelit != 0x0FFL)
7436 pic16_emitcode("anl","a,%s",
7437 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7438 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7444 // bit = left & literal
7447 pic16_emitpLabel(tlbl->key);
7449 // if(left & literal)
7452 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7455 pic16_emitpLabel(tlbl->key);
7460 pic16_outBitC(result);
7464 /* if left is same as result */
7465 if(pic16_sameRegs(AOP(result),AOP(left))){
7467 for(;size--; offset++,lit>>=8) {
7468 if(AOP_TYPE(right) == AOP_LIT){
7469 switch(lit & 0xff) {
7471 /* and'ing with 0 has clears the result */
7472 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7473 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7476 /* and'ing with 0xff is a nop when the result and left are the same */
7481 int p = pic16_my_powof2( (~lit) & 0xff );
7483 /* only one bit is set in the literal, so use a bcf instruction */
7484 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7485 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7488 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7489 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7490 if(know_W != (lit&0xff))
7491 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7493 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7498 if (AOP_TYPE(left) == AOP_ACC) {
7499 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7501 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7502 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7509 // left & result in different registers
7510 if(AOP_TYPE(result) == AOP_CRY){
7512 // if(size), result in bit
7513 // if(!size && ifx), conditional oper: if(left & right)
7514 symbol *tlbl = newiTempLabel(NULL);
7515 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7517 pic16_emitcode("setb","c");
7519 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7520 pic16_emitcode("anl","a,%s",
7521 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7522 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7527 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7528 pic16_outBitC(result);
7530 jmpTrueOrFalse(ifx, tlbl);
7532 for(;(size--);offset++) {
7534 // result = left & right
7535 if(AOP_TYPE(right) == AOP_LIT){
7536 int t = (lit >> (offset*8)) & 0x0FFL;
7539 pic16_emitcode("clrf","%s",
7540 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7541 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7544 pic16_emitcode("movf","%s,w",
7545 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7546 pic16_emitcode("movwf","%s",
7547 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7548 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7549 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7552 pic16_emitcode("movlw","0x%x",t);
7553 pic16_emitcode("andwf","%s,w",
7554 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7555 pic16_emitcode("movwf","%s",
7556 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7558 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7559 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7560 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7565 if (AOP_TYPE(left) == AOP_ACC) {
7566 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7567 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7569 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7570 pic16_emitcode("andwf","%s,w",
7571 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7572 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7573 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7575 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7576 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7582 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7583 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7584 pic16_freeAsmop(result,NULL,ic,TRUE);
7587 /*-----------------------------------------------------------------*/
7588 /* genOr - code for or */
7589 /*-----------------------------------------------------------------*/
7590 static void genOr (iCode *ic, iCode *ifx)
7592 operand *left, *right, *result;
7594 unsigned long lit = 0L;
7596 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7598 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7599 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7600 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7602 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7604 /* if left is a literal & right is not then exchange them */
7605 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7606 AOP_NEEDSACC(left)) {
7607 operand *tmp = right ;
7612 /* if result = right then exchange them */
7613 if(pic16_sameRegs(AOP(result),AOP(right))){
7614 operand *tmp = right ;
7619 /* if right is bit then exchange them */
7620 if (AOP_TYPE(right) == AOP_CRY &&
7621 AOP_TYPE(left) != AOP_CRY){
7622 operand *tmp = right ;
7627 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7629 if(AOP_TYPE(right) == AOP_LIT)
7630 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7632 size = AOP_SIZE(result);
7636 if (AOP_TYPE(left) == AOP_CRY){
7637 if(AOP_TYPE(right) == AOP_LIT){
7638 // c = bit & literal;
7640 // lit != 0 => result = 1
7641 if(AOP_TYPE(result) == AOP_CRY){
7643 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7644 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7645 // AOP(result)->aopu.aop_dir,
7646 // AOP(result)->aopu.aop_dir);
7648 continueIfTrue(ifx);
7652 // lit == 0 => result = left
7653 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7655 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7658 if (AOP_TYPE(right) == AOP_CRY){
7659 if(pic16_sameRegs(AOP(result),AOP(left))){
7661 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7662 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7663 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7665 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7666 AOP(result)->aopu.aop_dir,
7667 AOP(result)->aopu.aop_dir);
7668 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7669 AOP(right)->aopu.aop_dir,
7670 AOP(right)->aopu.aop_dir);
7671 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7672 AOP(result)->aopu.aop_dir,
7673 AOP(result)->aopu.aop_dir);
7675 if( AOP_TYPE(result) == AOP_ACC) {
7676 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7677 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7678 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7679 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7683 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7684 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7685 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7686 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7688 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7689 AOP(result)->aopu.aop_dir,
7690 AOP(result)->aopu.aop_dir);
7691 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7692 AOP(right)->aopu.aop_dir,
7693 AOP(right)->aopu.aop_dir);
7694 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7695 AOP(left)->aopu.aop_dir,
7696 AOP(left)->aopu.aop_dir);
7697 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7698 AOP(result)->aopu.aop_dir,
7699 AOP(result)->aopu.aop_dir);
7704 symbol *tlbl = newiTempLabel(NULL);
7705 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7708 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7709 if( AOP_TYPE(right) == AOP_ACC) {
7710 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7712 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7713 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7718 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7719 pic16_emitcode(";XXX setb","c");
7720 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7721 AOP(left)->aopu.aop_dir,tlbl->key+100);
7722 pic16_toBoolean(right);
7723 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7724 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7725 jmpTrueOrFalse(ifx, tlbl);
7729 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7736 pic16_outBitC(result);
7738 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7739 genIfxJump(ifx, "c");
7743 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7744 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7745 if((AOP_TYPE(right) == AOP_LIT) &&
7746 (AOP_TYPE(result) == AOP_CRY) &&
7747 (AOP_TYPE(left) != AOP_CRY)){
7749 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7752 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7754 continueIfTrue(ifx);
7757 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7758 // lit = 0, result = boolean(left)
7760 pic16_emitcode(";XXX setb","c");
7761 pic16_toBoolean(right);
7763 symbol *tlbl = newiTempLabel(NULL);
7764 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7766 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7768 genIfxJump (ifx,"a");
7772 pic16_outBitC(result);
7776 /* if left is same as result */
7777 if(pic16_sameRegs(AOP(result),AOP(left))){
7779 for(;size--; offset++,lit>>=8) {
7780 if(AOP_TYPE(right) == AOP_LIT){
7781 if((lit & 0xff) == 0)
7782 /* or'ing with 0 has no effect */
7785 int p = pic16_my_powof2(lit & 0xff);
7787 /* only one bit is set in the literal, so use a bsf instruction */
7788 pic16_emitpcode(POC_BSF,
7789 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7791 if(know_W != (lit & 0xff))
7792 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7793 know_W = lit & 0xff;
7794 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7799 if (AOP_TYPE(left) == AOP_ACC) {
7800 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7801 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7803 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7804 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7806 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7807 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7813 // left & result in different registers
7814 if(AOP_TYPE(result) == AOP_CRY){
7816 // if(size), result in bit
7817 // if(!size && ifx), conditional oper: if(left | right)
7818 symbol *tlbl = newiTempLabel(NULL);
7819 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7820 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7824 pic16_emitcode(";XXX setb","c");
7826 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7827 pic16_emitcode(";XXX orl","a,%s",
7828 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7829 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7834 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7835 pic16_outBitC(result);
7837 jmpTrueOrFalse(ifx, tlbl);
7838 } else for(;(size--);offset++){
7840 // result = left & right
7841 if(AOP_TYPE(right) == AOP_LIT){
7842 int t = (lit >> (offset*8)) & 0x0FFL;
7845 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7846 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7848 pic16_emitcode("movf","%s,w",
7849 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7850 pic16_emitcode("movwf","%s",
7851 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7854 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7855 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7856 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7858 pic16_emitcode("movlw","0x%x",t);
7859 pic16_emitcode("iorwf","%s,w",
7860 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7861 pic16_emitcode("movwf","%s",
7862 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7868 // faster than result <- left, anl result,right
7869 // and better if result is SFR
7870 if (AOP_TYPE(left) == AOP_ACC) {
7871 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7872 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7874 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7875 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7877 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7878 pic16_emitcode("iorwf","%s,w",
7879 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7881 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7882 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7887 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7888 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7889 pic16_freeAsmop(result,NULL,ic,TRUE);
7892 /*-----------------------------------------------------------------*/
7893 /* genXor - code for xclusive or */
7894 /*-----------------------------------------------------------------*/
7895 static void genXor (iCode *ic, iCode *ifx)
7897 operand *left, *right, *result;
7899 unsigned long lit = 0L;
7901 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7903 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7904 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7905 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7907 /* if left is a literal & right is not ||
7908 if left needs acc & right does not */
7909 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7910 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7911 operand *tmp = right ;
7916 /* if result = right then exchange them */
7917 if(pic16_sameRegs(AOP(result),AOP(right))){
7918 operand *tmp = right ;
7923 /* if right is bit then exchange them */
7924 if (AOP_TYPE(right) == AOP_CRY &&
7925 AOP_TYPE(left) != AOP_CRY){
7926 operand *tmp = right ;
7930 if(AOP_TYPE(right) == AOP_LIT)
7931 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7933 size = AOP_SIZE(result);
7937 if (AOP_TYPE(left) == AOP_CRY){
7938 if(AOP_TYPE(right) == AOP_LIT){
7939 // c = bit & literal;
7941 // lit>>1 != 0 => result = 1
7942 if(AOP_TYPE(result) == AOP_CRY){
7944 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
7945 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7947 continueIfTrue(ifx);
7950 pic16_emitcode("setb","c");
7954 // lit == 0, result = left
7955 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7957 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7959 // lit == 1, result = not(left)
7960 if(size && pic16_sameRegs(AOP(result),AOP(left))){
7961 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
7962 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
7963 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7966 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7967 pic16_emitcode("cpl","c");
7974 symbol *tlbl = newiTempLabel(NULL);
7975 if (AOP_TYPE(right) == AOP_CRY){
7977 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7980 int sizer = AOP_SIZE(right);
7982 // if val>>1 != 0, result = 1
7983 pic16_emitcode("setb","c");
7985 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7987 // test the msb of the lsb
7988 pic16_emitcode("anl","a,#0xfe");
7989 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7993 pic16_emitcode("rrc","a");
7995 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7996 pic16_emitcode("cpl","c");
7997 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8002 pic16_outBitC(result);
8004 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8005 genIfxJump(ifx, "c");
8009 if(pic16_sameRegs(AOP(result),AOP(left))){
8010 /* if left is same as result */
8011 for(;size--; offset++) {
8012 if(AOP_TYPE(right) == AOP_LIT){
8013 int t = (lit >> (offset*8)) & 0x0FFL;
8017 if (IS_AOP_PREG(left)) {
8018 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8019 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8020 pic16_aopPut(AOP(result),"a",offset);
8022 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8023 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8024 pic16_emitcode("xrl","%s,%s",
8025 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8026 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8029 if (AOP_TYPE(left) == AOP_ACC)
8030 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8032 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8033 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8035 if (IS_AOP_PREG(left)) {
8036 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8037 pic16_aopPut(AOP(result),"a",offset);
8039 pic16_emitcode("xrl","%s,a",
8040 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8046 // left & result in different registers
8047 if(AOP_TYPE(result) == AOP_CRY){
8049 // if(size), result in bit
8050 // if(!size && ifx), conditional oper: if(left ^ right)
8051 symbol *tlbl = newiTempLabel(NULL);
8052 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8054 pic16_emitcode("setb","c");
8056 if((AOP_TYPE(right) == AOP_LIT) &&
8057 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8058 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8060 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8061 pic16_emitcode("xrl","a,%s",
8062 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8064 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8069 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8070 pic16_outBitC(result);
8072 jmpTrueOrFalse(ifx, tlbl);
8073 } else for(;(size--);offset++){
8075 // result = left & right
8076 if(AOP_TYPE(right) == AOP_LIT){
8077 int t = (lit >> (offset*8)) & 0x0FFL;
8080 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8081 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8082 pic16_emitcode("movf","%s,w",
8083 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8084 pic16_emitcode("movwf","%s",
8085 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8088 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8089 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8090 pic16_emitcode("comf","%s,w",
8091 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8092 pic16_emitcode("movwf","%s",
8093 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8096 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8097 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8098 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8099 pic16_emitcode("movlw","0x%x",t);
8100 pic16_emitcode("xorwf","%s,w",
8101 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8102 pic16_emitcode("movwf","%s",
8103 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8109 // faster than result <- left, anl result,right
8110 // and better if result is SFR
8111 if (AOP_TYPE(left) == AOP_ACC) {
8112 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8113 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8115 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8116 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8117 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8118 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8120 if ( AOP_TYPE(result) != AOP_ACC){
8121 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8122 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8128 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8129 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8130 pic16_freeAsmop(result,NULL,ic,TRUE);
8133 /*-----------------------------------------------------------------*/
8134 /* genInline - write the inline code out */
8135 /*-----------------------------------------------------------------*/
8136 static void genInline (iCode *ic)
8138 char *buffer, *bp, *bp1;
8140 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8142 _G.inLine += (!options.asmpeep);
8144 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8145 strcpy(buffer,IC_INLINE(ic));
8147 while((bp1=strstr(bp, "\\n"))) {
8155 /* This is an experimental code for #pragma inline
8156 and is temporarily disabled for 2.5.0 release */
8164 cbuf = Safe_strdup(buffer);
8165 cblen = strlen(buffer)+1;
8166 memset(cbuf, 0, cblen);
8171 if(*bp != '%')*bp1++ = *bp++;
8177 if(i>elementsInSet(asmInlineMap))break;
8180 s = indexSet(asmInlineMap, i);
8181 DEBUGpc("searching symbol s = `%s'", s);
8182 sym = findSym(SymbolTab, NULL, s);
8185 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8187 strcat(bp1, sym->rname);
8193 if(strlen(bp1) > cblen - 16) {
8194 int i = strlen(cbuf);
8196 cbuf = realloc(cbuf, cblen);
8197 memset(cbuf+i, 0, 50);
8203 buffer = Safe_strdup( cbuf );
8210 /* emit each line as a code */
8216 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8224 /* print label, use this special format with NULL directive
8225 * to denote that the argument should not be indented with tab */
8226 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8229 /* advance to end of line (prevent splitting of comments at ':' */
8230 while (*bp && *bp != '\n') {
8238 if ((bp1 != bp) && *bp1)
8239 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8244 _G.inLine -= (!options.asmpeep);
8247 /*-----------------------------------------------------------------*/
8248 /* genRRC - rotate right with carry */
8249 /*-----------------------------------------------------------------*/
8250 static void genRRC (iCode *ic)
8252 operand *left , *result ;
8253 int size, offset = 0, same;
8255 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8257 /* rotate right with carry */
8259 result=IC_RESULT(ic);
8260 pic16_aopOp (left,ic,FALSE);
8261 pic16_aopOp (result,ic,TRUE);
8263 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8265 same = pic16_sameRegs(AOP(result),AOP(left));
8267 size = AOP_SIZE(result);
8269 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8271 /* get the lsb and put it into the carry */
8272 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8279 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8281 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8282 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8288 pic16_freeAsmop(left,NULL,ic,TRUE);
8289 pic16_freeAsmop(result,NULL,ic,TRUE);
8292 /*-----------------------------------------------------------------*/
8293 /* genRLC - generate code for rotate left with carry */
8294 /*-----------------------------------------------------------------*/
8295 static void genRLC (iCode *ic)
8297 operand *left , *result ;
8298 int size, offset = 0;
8301 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8302 /* rotate right with carry */
8304 result=IC_RESULT(ic);
8305 pic16_aopOp (left,ic,FALSE);
8306 pic16_aopOp (result,ic,TRUE);
8308 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8310 same = pic16_sameRegs(AOP(result),AOP(left));
8312 /* move it to the result */
8313 size = AOP_SIZE(result);
8315 /* get the msb and put it into the carry */
8316 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8323 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8325 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8326 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8333 pic16_freeAsmop(left,NULL,ic,TRUE);
8334 pic16_freeAsmop(result,NULL,ic,TRUE);
8338 /* gpasm can get the highest order bit with HIGH/UPPER
8339 * so the following probably is not needed -- VR */
8341 /*-----------------------------------------------------------------*/
8342 /* genGetHbit - generates code get highest order bit */
8343 /*-----------------------------------------------------------------*/
8344 static void genGetHbit (iCode *ic)
8346 operand *left, *result;
8348 result=IC_RESULT(ic);
8349 pic16_aopOp (left,ic,FALSE);
8350 pic16_aopOp (result,ic,FALSE);
8352 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8353 /* get the highest order byte into a */
8354 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8355 if(AOP_TYPE(result) == AOP_CRY){
8356 pic16_emitcode("rlc","a");
8357 pic16_outBitC(result);
8360 pic16_emitcode("rl","a");
8361 pic16_emitcode("anl","a,#0x01");
8362 pic16_outAcc(result);
8366 pic16_freeAsmop(left,NULL,ic,TRUE);
8367 pic16_freeAsmop(result,NULL,ic,TRUE);
8371 /*-----------------------------------------------------------------*/
8372 /* AccRol - rotate left accumulator by known count */
8373 /*-----------------------------------------------------------------*/
8374 static void AccRol (int shCount)
8376 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8377 shCount &= 0x0007; // shCount : 0..7
8382 pic16_emitcode("rl","a");
8385 pic16_emitcode("rl","a");
8386 pic16_emitcode("rl","a");
8389 pic16_emitcode("swap","a");
8390 pic16_emitcode("rr","a");
8393 pic16_emitcode("swap","a");
8396 pic16_emitcode("swap","a");
8397 pic16_emitcode("rl","a");
8400 pic16_emitcode("rr","a");
8401 pic16_emitcode("rr","a");
8404 pic16_emitcode("rr","a");
8410 /*-----------------------------------------------------------------*/
8411 /* AccLsh - left shift accumulator by known count */
8412 /*-----------------------------------------------------------------*/
8413 static void AccLsh (int shCount)
8415 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8421 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8424 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8425 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8428 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8429 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8432 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8435 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8436 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8439 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8440 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8443 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8447 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8450 /*-----------------------------------------------------------------*/
8451 /* AccRsh - right shift accumulator by known count */
8452 /*-----------------------------------------------------------------*/
8453 static void AccRsh (int shCount, int andmask)
8455 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8460 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8463 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8464 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8467 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8468 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8471 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8474 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8475 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8478 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8479 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8482 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8487 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8489 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8493 /*-----------------------------------------------------------------*/
8494 /* AccSRsh - signed right shift accumulator by known count */
8495 /*-----------------------------------------------------------------*/
8496 static void AccSRsh (int shCount)
8499 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8502 pic16_emitcode("mov","c,acc.7");
8503 pic16_emitcode("rrc","a");
8504 } else if(shCount == 2){
8505 pic16_emitcode("mov","c,acc.7");
8506 pic16_emitcode("rrc","a");
8507 pic16_emitcode("mov","c,acc.7");
8508 pic16_emitcode("rrc","a");
8510 tlbl = newiTempLabel(NULL);
8511 /* rotate right accumulator */
8512 AccRol(8 - shCount);
8513 /* and kill the higher order bits */
8514 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8515 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8516 pic16_emitcode("orl","a,#0x%02x",
8517 (unsigned char)~SRMask[shCount]);
8518 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8524 /*-----------------------------------------------------------------*/
8525 /* shiftR1Left2Result - shift right one byte from left to result */
8526 /*-----------------------------------------------------------------*/
8527 static void shiftR1Left2ResultSigned (operand *left, int offl,
8528 operand *result, int offr,
8533 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8535 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8539 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8541 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8543 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8544 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8550 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8552 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8554 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8555 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8557 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8558 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8564 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8566 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8567 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8570 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8571 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8572 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8574 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8575 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8577 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8581 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8582 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8583 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8584 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8585 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8589 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8591 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8592 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8594 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8595 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8596 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8597 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8598 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8603 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8604 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8605 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8606 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8607 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8608 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8610 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8611 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8612 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8613 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8614 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8620 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8621 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8622 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8623 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8625 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8626 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8627 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8635 /*-----------------------------------------------------------------*/
8636 /* shiftR1Left2Result - shift right one byte from left to result */
8637 /*-----------------------------------------------------------------*/
8638 static void shiftR1Left2Result (operand *left, int offl,
8639 operand *result, int offr,
8640 int shCount, int sign)
8644 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8646 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8648 /* Copy the msb into the carry if signed. */
8650 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8660 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8662 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8663 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8669 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8671 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8672 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8675 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8680 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8682 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8683 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8686 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8687 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8688 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8689 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8693 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8694 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8695 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8699 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8700 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8701 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8703 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8708 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8709 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8710 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8711 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8712 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8717 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8718 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8719 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8728 /*-----------------------------------------------------------------*/
8729 /* shiftL1Left2Result - shift left one byte from left to result */
8730 /*-----------------------------------------------------------------*/
8731 static void shiftL1Left2Result (operand *left, int offl,
8732 operand *result, int offr, int shCount)
8737 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8739 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8740 DEBUGpic16_emitcode ("; ***","same = %d",same);
8741 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8743 /* shift left accumulator */
8744 //AccLsh(shCount); // don't comment out just yet...
8745 // pic16_aopPut(AOP(result),"a",offr);
8749 /* Shift left 1 bit position */
8750 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8752 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8754 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8755 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8759 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8760 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8761 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8762 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8765 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8766 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8767 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8768 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8769 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8772 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8773 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8774 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8777 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8778 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8779 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8780 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8783 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8784 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8785 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8786 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8787 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8790 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8791 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8792 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8796 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8801 /*-----------------------------------------------------------------*/
8802 /* movLeft2Result - move byte from left to result */
8803 /*-----------------------------------------------------------------*/
8804 static void movLeft2Result (operand *left, int offl,
8805 operand *result, int offr)
8808 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8809 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8810 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8812 if (*l == '@' && (IS_AOP_PREG(result))) {
8813 pic16_emitcode("mov","a,%s",l);
8814 pic16_aopPut(AOP(result),"a",offr);
8816 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8817 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8822 /*-----------------------------------------------------------------*/
8823 /* shiftL2Left2Result - shift left two bytes from left to result */
8824 /*-----------------------------------------------------------------*/
8825 static void shiftL2Left2Result (operand *left, int offl,
8826 operand *result, int offr, int shCount)
8828 int same = pic16_sameRegs(AOP(result), AOP(left));
8831 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8833 if (same && (offl != offr)) { // shift bytes
8836 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8837 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8839 } else { // just treat as different later on
8852 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8853 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8854 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8858 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8859 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8865 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8866 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8867 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8868 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8869 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8870 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8871 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8873 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8874 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8878 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8879 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8880 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8881 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8882 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8883 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8884 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8885 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8886 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8887 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8890 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8891 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8892 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8893 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8894 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8904 /* note, use a mov/add for the shift since the mov has a
8905 chance of getting optimized out */
8906 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8907 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8908 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8909 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8910 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8914 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8915 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8921 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8922 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8923 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8924 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8925 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8926 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8927 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8928 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8932 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8933 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8937 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8938 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8939 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8940 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8942 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8943 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8944 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8945 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8946 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8947 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8948 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8949 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8952 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8953 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8954 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8955 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8956 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8961 /*-----------------------------------------------------------------*/
8962 /* shiftR2Left2Result - shift right two bytes from left to result */
8963 /*-----------------------------------------------------------------*/
8964 static void shiftR2Left2Result (operand *left, int offl,
8965 operand *result, int offr,
8966 int shCount, int sign)
8968 int same = pic16_sameRegs(AOP(result), AOP(left));
8970 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8972 if (same && (offl != offr)) { // shift right bytes
8975 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8976 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8978 } else { // just treat as different later on
8990 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8995 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8996 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8998 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8999 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9000 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9001 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9006 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9009 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9010 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9017 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9018 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9019 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9021 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9022 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9023 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9024 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9026 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9027 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9028 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9030 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9031 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9032 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9033 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9034 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9038 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9039 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9043 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9044 pic16_emitpcode(POC_BTFSC,
9045 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9046 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9054 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9055 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9057 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9058 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9059 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9060 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9062 pic16_emitpcode(POC_BTFSC,
9063 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9064 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9066 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9067 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9068 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9069 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9071 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9072 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9073 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9074 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9075 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9076 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9077 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9078 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9080 pic16_emitpcode(POC_BTFSC,
9081 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9082 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9084 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9085 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9092 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9093 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9094 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9095 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9098 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9100 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9105 /*-----------------------------------------------------------------*/
9106 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9107 /*-----------------------------------------------------------------*/
9108 static void shiftLLeftOrResult (operand *left, int offl,
9109 operand *result, int offr, int shCount)
9111 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9113 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9114 /* shift left accumulator */
9116 /* or with result */
9117 /* back to result */
9118 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9121 /*-----------------------------------------------------------------*/
9122 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9123 /*-----------------------------------------------------------------*/
9124 static void shiftRLeftOrResult (operand *left, int offl,
9125 operand *result, int offr, int shCount)
9127 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9129 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9130 /* shift right accumulator */
9132 /* or with result */
9133 /* back to result */
9134 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9137 /*-----------------------------------------------------------------*/
9138 /* genlshOne - left shift a one byte quantity by known count */
9139 /*-----------------------------------------------------------------*/
9140 static void genlshOne (operand *result, operand *left, int shCount)
9142 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9143 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9146 /*-----------------------------------------------------------------*/
9147 /* genlshTwo - left shift two bytes by known amount != 0 */
9148 /*-----------------------------------------------------------------*/
9149 static void genlshTwo (operand *result,operand *left, int shCount)
9153 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9154 size = pic16_getDataSize(result);
9156 /* if shCount >= 8 */
9162 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9164 movLeft2Result(left, LSB, result, MSB16);
9166 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9169 /* 1 <= shCount <= 7 */
9172 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9174 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9178 /*-----------------------------------------------------------------*/
9179 /* shiftLLong - shift left one long from left to result */
9180 /* offr = LSB or MSB16 */
9181 /*-----------------------------------------------------------------*/
9182 static void shiftLLong (operand *left, operand *result, int offr )
9184 int size = AOP_SIZE(result);
9185 int same = pic16_sameRegs(AOP(left),AOP(result));
9188 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9190 if (same && (offr == MSB16)) { //shift one byte
9191 for(i=size-1;i>=MSB16;i--) {
9192 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9193 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9196 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9199 if (size > LSB+offr ){
9201 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9203 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9204 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9208 if(size > MSB16+offr){
9210 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9212 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9213 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9217 if(size > MSB24+offr){
9219 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9221 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9222 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9226 if(size > MSB32+offr){
9228 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9230 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9231 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9235 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9239 /*-----------------------------------------------------------------*/
9240 /* genlshFour - shift four byte by a known amount != 0 */
9241 /*-----------------------------------------------------------------*/
9242 static void genlshFour (operand *result, operand *left, int shCount)
9246 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9247 size = AOP_SIZE(result);
9249 /* if shifting more that 3 bytes */
9250 if (shCount >= 24 ) {
9253 /* lowest order of left goes to the highest
9254 order of the destination */
9255 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9257 movLeft2Result(left, LSB, result, MSB32);
9259 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9260 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9261 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9266 /* more than two bytes */
9267 else if ( shCount >= 16 ) {
9268 /* lower order two bytes goes to higher order two bytes */
9270 /* if some more remaining */
9272 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9274 movLeft2Result(left, MSB16, result, MSB32);
9275 movLeft2Result(left, LSB, result, MSB24);
9277 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9278 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9282 /* if more than 1 byte */
9283 else if ( shCount >= 8 ) {
9284 /* lower order three bytes goes to higher order three bytes */
9288 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9290 movLeft2Result(left, LSB, result, MSB16);
9292 else{ /* size = 4 */
9294 movLeft2Result(left, MSB24, result, MSB32);
9295 movLeft2Result(left, MSB16, result, MSB24);
9296 movLeft2Result(left, LSB, result, MSB16);
9297 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9299 else if(shCount == 1)
9300 shiftLLong(left, result, MSB16);
9302 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9303 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9304 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9305 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9310 /* 1 <= shCount <= 7 */
9311 else if(shCount <= 3)
9313 shiftLLong(left, result, LSB);
9314 while(--shCount >= 1)
9315 shiftLLong(result, result, LSB);
9317 /* 3 <= shCount <= 7, optimize */
9319 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9320 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9321 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9325 /*-----------------------------------------------------------------*/
9326 /* genLeftShiftLiteral - left shifting by known count */
9327 /*-----------------------------------------------------------------*/
9328 void pic16_genLeftShiftLiteral (operand *left,
9333 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9337 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9338 pic16_freeAsmop(right,NULL,ic,TRUE);
9340 pic16_aopOp(left,ic,FALSE);
9341 pic16_aopOp(result,ic,TRUE);
9343 size = getSize(operandType(result));
9346 pic16_emitcode("; shift left ","result %d, left %d",size,
9350 /* I suppose that the left size >= result size */
9353 movLeft2Result(left, size, result, size);
9357 else if(shCount >= (size * 8))
9359 pic16_aopPut(AOP(result),zero,size);
9363 genlshOne (result,left,shCount);
9368 genlshTwo (result,left,shCount);
9372 genlshFour (result,left,shCount);
9376 pic16_freeAsmop(left,NULL,ic,TRUE);
9377 pic16_freeAsmop(result,NULL,ic,TRUE);
9380 /*-----------------------------------------------------------------*
9381 * genMultiAsm - repeat assembly instruction for size of register.
9382 * if endian == 1, then the high byte (i.e base address + size of
9383 * register) is used first else the low byte is used first;
9384 *-----------------------------------------------------------------*/
9385 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9390 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9403 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9409 #if !(USE_GENERIC_SIGNED_SHIFT)
9410 /*-----------------------------------------------------------------*/
9411 /* genLeftShift - generates code for left shifting */
9412 /*-----------------------------------------------------------------*/
9413 static void genLeftShift (iCode *ic)
9415 operand *left,*right, *result;
9418 symbol *tlbl , *tlbl1;
9421 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9423 right = IC_RIGHT(ic);
9425 result = IC_RESULT(ic);
9427 pic16_aopOp(right,ic,FALSE);
9429 /* if the shift count is known then do it
9430 as efficiently as possible */
9431 if (AOP_TYPE(right) == AOP_LIT) {
9432 pic16_genLeftShiftLiteral (left,right,result,ic);
9436 /* shift count is unknown then we have to form
9437 * a loop. Get the loop count in WREG : Note: we take
9438 * only the lower order byte since shifting
9439 * more than 32 bits make no sense anyway, ( the
9440 * largest size of an object can be only 32 bits ) */
9442 pic16_aopOp(left,ic,FALSE);
9443 pic16_aopOp(result,ic,FALSE);
9445 /* now move the left to the result if they are not the
9446 * same, and if size > 1,
9447 * and if right is not same to result (!!!) -- VR */
9448 if (!pic16_sameRegs(AOP(left),AOP(result))
9449 && (AOP_SIZE(result) > 1)) {
9451 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9453 size = AOP_SIZE(result);
9458 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9459 if (*l == '@' && (IS_AOP_PREG(result))) {
9461 pic16_emitcode("mov","a,%s",l);
9462 pic16_aopPut(AOP(result),"a",offset);
9466 /* we don't know if left is a literal or a register, take care -- VR */
9467 pic16_mov2f(AOP(result), AOP(left), offset);
9473 size = AOP_SIZE(result);
9475 /* if it is only one byte then */
9477 if(optimized_for_speed) {
9478 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9479 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9480 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9481 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9482 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9483 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9484 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9485 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9486 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9487 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9488 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9489 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9492 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9494 tlbl = newiTempLabel(NULL);
9497 /* this is already done, why change it? */
9498 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9499 pic16_mov2f(AOP(result), AOP(left), 0);
9503 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9504 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9505 pic16_emitpLabel(tlbl->key);
9506 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9507 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9509 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9514 if (pic16_sameRegs(AOP(left),AOP(result))) {
9516 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9518 tlbl = newiTempLabel(NULL);
9519 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9520 genMultiAsm(POC_RRCF, result, size,1);
9521 pic16_emitpLabel(tlbl->key);
9522 genMultiAsm(POC_RLCF, result, size,0);
9523 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9525 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9529 //tlbl = newiTempLabel(NULL);
9531 //tlbl1 = newiTempLabel(NULL);
9533 //reAdjustPreg(AOP(result));
9535 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9536 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9537 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9539 //pic16_emitcode("add","a,acc");
9540 //pic16_aopPut(AOP(result),"a",offset++);
9542 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9544 // pic16_emitcode("rlc","a");
9545 // pic16_aopPut(AOP(result),"a",offset++);
9547 //reAdjustPreg(AOP(result));
9549 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9550 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9553 tlbl = newiTempLabel(NULL);
9554 tlbl1= newiTempLabel(NULL);
9556 size = AOP_SIZE(result);
9559 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9561 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9563 /* offset should be 0, 1 or 3 */
9565 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9567 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9569 pic16_emitpcode(POC_MOVWF, pctemp);
9572 pic16_emitpLabel(tlbl->key);
9575 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9577 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9579 pic16_emitpcode(POC_DECFSZ, pctemp);
9580 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9581 pic16_emitpLabel(tlbl1->key);
9583 pic16_popReleaseTempReg(pctemp,1);
9587 pic16_freeAsmop (right,NULL,ic,TRUE);
9588 pic16_freeAsmop(left,NULL,ic,TRUE);
9589 pic16_freeAsmop(result,NULL,ic,TRUE);
9595 #error old code (left here for reference)
9596 /*-----------------------------------------------------------------*/
9597 /* genLeftShift - generates code for left shifting */
9598 /*-----------------------------------------------------------------*/
9599 static void genLeftShift (iCode *ic)
9601 operand *left,*right, *result;
9604 symbol *tlbl , *tlbl1;
9607 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9609 right = IC_RIGHT(ic);
9611 result = IC_RESULT(ic);
9613 pic16_aopOp(right,ic,FALSE);
9615 /* if the shift count is known then do it
9616 as efficiently as possible */
9617 if (AOP_TYPE(right) == AOP_LIT) {
9618 pic16_genLeftShiftLiteral (left,right,result,ic);
9622 /* shift count is unknown then we have to form
9623 a loop get the loop count in B : Note: we take
9624 only the lower order byte since shifting
9625 more that 32 bits make no sense anyway, ( the
9626 largest size of an object can be only 32 bits ) */
9629 pic16_aopOp(left,ic,FALSE);
9630 pic16_aopOp(result,ic,FALSE);
9632 /* now move the left to the result if they are not the
9634 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9635 AOP_SIZE(result) > 1) {
9637 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9639 size = AOP_SIZE(result);
9642 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9643 if (*l == '@' && (IS_AOP_PREG(result))) {
9645 pic16_emitcode("mov","a,%s",l);
9646 pic16_aopPut(AOP(result),"a",offset);
9649 /* we don't know if left is a literal or a register, take care -- VR */
9650 pic16_mov2f(AOP(result), AOP(left), offset);
9656 size = AOP_SIZE(result);
9658 /* if it is only one byte then */
9660 if(optimized_for_speed) {
9661 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9662 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9663 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9664 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9665 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9666 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9667 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9668 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9669 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9670 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9671 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9672 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9675 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9677 tlbl = newiTempLabel(NULL);
9678 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9679 pic16_mov2f(AOP(result), AOP(left), 0);
9681 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9682 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9685 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9686 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9687 pic16_emitpLabel(tlbl->key);
9688 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9689 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9691 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9696 if (pic16_sameRegs(AOP(left),AOP(result))) {
9698 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9700 tlbl = newiTempLabel(NULL);
9701 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9702 genMultiAsm(POC_RRCF, result, size,1);
9703 pic16_emitpLabel(tlbl->key);
9704 genMultiAsm(POC_RLCF, result, size,0);
9705 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9707 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9711 //tlbl = newiTempLabel(NULL);
9713 //tlbl1 = newiTempLabel(NULL);
9715 //reAdjustPreg(AOP(result));
9717 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9718 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9719 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9721 //pic16_emitcode("add","a,acc");
9722 //pic16_aopPut(AOP(result),"a",offset++);
9724 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9726 // pic16_emitcode("rlc","a");
9727 // pic16_aopPut(AOP(result),"a",offset++);
9729 //reAdjustPreg(AOP(result));
9731 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9732 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9735 tlbl = newiTempLabel(NULL);
9736 tlbl1= newiTempLabel(NULL);
9738 size = AOP_SIZE(result);
9741 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9743 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9745 /* offset should be 0, 1 or 3 */
9747 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9749 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9751 pic16_emitpcode(POC_MOVWF, pctemp);
9754 pic16_emitpLabel(tlbl->key);
9757 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9759 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9761 pic16_emitpcode(POC_DECFSZ, pctemp);
9762 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9763 pic16_emitpLabel(tlbl1->key);
9765 pic16_popReleaseTempReg(pctemp,1);
9769 pic16_freeAsmop (right,NULL,ic,TRUE);
9770 pic16_freeAsmop(left,NULL,ic,TRUE);
9771 pic16_freeAsmop(result,NULL,ic,TRUE);
9775 /*-----------------------------------------------------------------*/
9776 /* genrshOne - right shift a one byte quantity by known count */
9777 /*-----------------------------------------------------------------*/
9778 static void genrshOne (operand *result, operand *left,
9779 int shCount, int sign)
9781 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9782 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9785 /*-----------------------------------------------------------------*/
9786 /* genrshTwo - right shift two bytes by known amount != 0 */
9787 /*-----------------------------------------------------------------*/
9788 static void genrshTwo (operand *result,operand *left,
9789 int shCount, int sign)
9791 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9792 /* if shCount >= 8 */
9796 shiftR1Left2Result(left, MSB16, result, LSB,
9799 movLeft2Result(left, MSB16, result, LSB);
9801 pic16_addSign (result, 1, sign);
9804 /* 1 <= shCount <= 7 */
9806 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9809 /*-----------------------------------------------------------------*/
9810 /* shiftRLong - shift right one long from left to result */
9811 /* offl = LSB or MSB16 */
9812 /*-----------------------------------------------------------------*/
9813 static void shiftRLong (operand *left, int offl,
9814 operand *result, int sign)
9816 int size = AOP_SIZE(result);
9817 int same = pic16_sameRegs(AOP(left),AOP(result));
9819 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9821 if (same && (offl == MSB16)) { //shift one byte right
9822 for(i=MSB16;i<size;i++) {
9823 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9824 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9829 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9835 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9837 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9838 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9842 /* add sign of "a" */
9843 pic16_addSign(result, MSB32, sign);
9847 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9849 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9850 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9854 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9856 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9857 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9861 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9864 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9865 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9870 /*-----------------------------------------------------------------*/
9871 /* genrshFour - shift four byte by a known amount != 0 */
9872 /*-----------------------------------------------------------------*/
9873 static void genrshFour (operand *result, operand *left,
9874 int shCount, int sign)
9876 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9877 /* if shifting more that 3 bytes */
9878 if(shCount >= 24 ) {
9881 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9883 movLeft2Result(left, MSB32, result, LSB);
9885 pic16_addSign(result, MSB16, sign);
9887 else if(shCount >= 16){
9890 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9892 movLeft2Result(left, MSB24, result, LSB);
9893 movLeft2Result(left, MSB32, result, MSB16);
9895 pic16_addSign(result, MSB24, sign);
9897 else if(shCount >= 8){
9900 shiftRLong(left, MSB16, result, sign);
9901 else if(shCount == 0){
9902 movLeft2Result(left, MSB16, result, LSB);
9903 movLeft2Result(left, MSB24, result, MSB16);
9904 movLeft2Result(left, MSB32, result, MSB24);
9905 pic16_addSign(result, MSB32, sign);
9907 else{ //shcount >= 2
9908 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9909 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9910 /* the last shift is signed */
9911 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9912 pic16_addSign(result, MSB32, sign);
9915 else{ /* 1 <= shCount <= 7 */
9917 shiftRLong(left, LSB, result, sign);
9919 shiftRLong(result, LSB, result, sign);
9922 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9923 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9924 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9929 /*-----------------------------------------------------------------*/
9930 /* genRightShiftLiteral - right shifting by known count */
9931 /*-----------------------------------------------------------------*/
9932 static void genRightShiftLiteral (operand *left,
9938 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9941 pic16_freeAsmop(right,NULL,ic,TRUE);
9943 pic16_aopOp(left,ic,FALSE);
9944 pic16_aopOp(result,ic,TRUE);
9946 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9949 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9953 lsize = pic16_getDataSize(left);
9954 res_size = pic16_getDataSize(result);
9955 /* test the LEFT size !!! */
9957 /* I suppose that the left size >= result size */
9959 assert (res_size <= lsize);
9960 while (res_size--) {
9961 pic16_mov2f (AOP(result), AOP(left), res_size);
9965 else if(shCount >= (lsize * 8)){
9968 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9970 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9971 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
9976 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9977 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9978 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9980 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9985 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9992 genrshOne (result,left,shCount,sign);
9996 genrshTwo (result,left,shCount,sign);
10000 genrshFour (result,left,shCount,sign);
10008 pic16_freeAsmop(left,NULL,ic,TRUE);
10009 pic16_freeAsmop(result,NULL,ic,TRUE);
10012 #if !(USE_GENERIC_SIGNED_SHIFT)
10013 /*-----------------------------------------------------------------*/
10014 /* genSignedRightShift - right shift of signed number */
10015 /*-----------------------------------------------------------------*/
10016 static void genSignedRightShift (iCode *ic)
10018 operand *right, *left, *result;
10021 symbol *tlbl, *tlbl1 ;
10024 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10026 /* we do it the hard way put the shift count in b
10027 and loop thru preserving the sign */
10028 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10030 right = IC_RIGHT(ic);
10031 left = IC_LEFT(ic);
10032 result = IC_RESULT(ic);
10034 pic16_aopOp(right,ic,FALSE);
10035 pic16_aopOp(left,ic,FALSE);
10036 pic16_aopOp(result,ic,FALSE);
10039 if ( AOP_TYPE(right) == AOP_LIT) {
10040 genRightShiftLiteral (left,right,result,ic,1);
10043 /* shift count is unknown then we have to form
10044 a loop get the loop count in B : Note: we take
10045 only the lower order byte since shifting
10046 more that 32 bits make no sense anyway, ( the
10047 largest size of an object can be only 32 bits ) */
10049 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10050 //pic16_emitcode("inc","b");
10051 //pic16_freeAsmop (right,NULL,ic,TRUE);
10052 //pic16_aopOp(left,ic,FALSE);
10053 //pic16_aopOp(result,ic,FALSE);
10055 /* now move the left to the result if they are not the
10057 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10058 AOP_SIZE(result) > 1) {
10060 size = AOP_SIZE(result);
10064 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10065 if (*l == '@' && IS_AOP_PREG(result)) {
10067 pic16_emitcode("mov","a,%s",l);
10068 pic16_aopPut(AOP(result),"a",offset);
10070 pic16_aopPut(AOP(result),l,offset);
10072 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10073 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10079 /* mov the highest order bit to OVR */
10080 tlbl = newiTempLabel(NULL);
10081 tlbl1= newiTempLabel(NULL);
10083 size = AOP_SIZE(result);
10086 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10088 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10090 /* offset should be 0, 1 or 3 */
10091 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10093 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10095 pic16_emitpcode(POC_MOVWF, pctemp);
10098 pic16_emitpLabel(tlbl->key);
10100 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10101 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10104 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10107 pic16_emitpcode(POC_DECFSZ, pctemp);
10108 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10109 pic16_emitpLabel(tlbl1->key);
10111 pic16_popReleaseTempReg(pctemp,1);
10113 size = AOP_SIZE(result);
10115 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10116 pic16_emitcode("rlc","a");
10117 pic16_emitcode("mov","ov,c");
10118 /* if it is only one byte then */
10120 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10122 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10123 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10124 pic16_emitcode("mov","c,ov");
10125 pic16_emitcode("rrc","a");
10126 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10127 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10128 pic16_aopPut(AOP(result),"a",0);
10132 reAdjustPreg(AOP(result));
10133 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10134 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10135 pic16_emitcode("mov","c,ov");
10137 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10139 pic16_emitcode("rrc","a");
10140 pic16_aopPut(AOP(result),"a",offset--);
10142 reAdjustPreg(AOP(result));
10143 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10144 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10149 pic16_freeAsmop(left,NULL,ic,TRUE);
10150 pic16_freeAsmop(result,NULL,ic,TRUE);
10151 pic16_freeAsmop(right,NULL,ic,TRUE);
10155 #if !(USE_GENERIC_SIGNED_SHIFT)
10156 #warning This implementation of genRightShift() is incomplete!
10157 /*-----------------------------------------------------------------*/
10158 /* genRightShift - generate code for right shifting */
10159 /*-----------------------------------------------------------------*/
10160 static void genRightShift (iCode *ic)
10162 operand *right, *left, *result;
10166 symbol *tlbl, *tlbl1 ;
10168 /* if signed then we do it the hard way preserve the
10169 sign bit moving it inwards */
10170 letype = getSpec(operandType(IC_LEFT(ic)));
10171 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10173 if (!SPEC_USIGN(letype)) {
10174 genSignedRightShift (ic);
10178 /* signed & unsigned types are treated the same : i.e. the
10179 signed is NOT propagated inwards : quoting from the
10180 ANSI - standard : "for E1 >> E2, is equivalent to division
10181 by 2**E2 if unsigned or if it has a non-negative value,
10182 otherwise the result is implementation defined ", MY definition
10183 is that the sign does not get propagated */
10185 right = IC_RIGHT(ic);
10186 left = IC_LEFT(ic);
10187 result = IC_RESULT(ic);
10189 pic16_aopOp(right,ic,FALSE);
10191 /* if the shift count is known then do it
10192 as efficiently as possible */
10193 if (AOP_TYPE(right) == AOP_LIT) {
10194 genRightShiftLiteral (left,right,result,ic, 0);
10198 /* shift count is unknown then we have to form
10199 a loop get the loop count in B : Note: we take
10200 only the lower order byte since shifting
10201 more that 32 bits make no sense anyway, ( the
10202 largest size of an object can be only 32 bits ) */
10204 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10205 pic16_emitcode("inc","b");
10206 pic16_aopOp(left,ic,FALSE);
10207 pic16_aopOp(result,ic,FALSE);
10209 /* now move the left to the result if they are not the
10211 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10212 AOP_SIZE(result) > 1) {
10214 size = AOP_SIZE(result);
10217 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10218 if (*l == '@' && IS_AOP_PREG(result)) {
10220 pic16_emitcode("mov","a,%s",l);
10221 pic16_aopPut(AOP(result),"a",offset);
10223 pic16_aopPut(AOP(result),l,offset);
10228 tlbl = newiTempLabel(NULL);
10229 tlbl1= newiTempLabel(NULL);
10230 size = AOP_SIZE(result);
10233 /* if it is only one byte then */
10236 tlbl = newiTempLabel(NULL);
10237 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10238 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10239 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10242 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10243 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10244 pic16_emitpLabel(tlbl->key);
10245 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10246 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10248 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10253 reAdjustPreg(AOP(result));
10254 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10255 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10258 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10260 pic16_emitcode("rrc","a");
10261 pic16_aopPut(AOP(result),"a",offset--);
10263 reAdjustPreg(AOP(result));
10265 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10266 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10269 pic16_freeAsmop(left,NULL,ic,TRUE);
10270 pic16_freeAsmop (right,NULL,ic,TRUE);
10271 pic16_freeAsmop(result,NULL,ic,TRUE);
10275 #if (USE_GENERIC_SIGNED_SHIFT)
10276 /*-----------------------------------------------------------------*/
10277 /* genGenericShift - generates code for left or right shifting */
10278 /*-----------------------------------------------------------------*/
10279 static void genGenericShift (iCode *ic, int isShiftLeft) {
10280 operand *left,*right, *result;
10282 int sign, signedCount;
10283 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10284 PIC_OPCODE pos_shift, neg_shift;
10288 right = IC_RIGHT(ic);
10289 left = IC_LEFT(ic);
10290 result = IC_RESULT(ic);
10292 pic16_aopOp(right,ic,FALSE);
10293 pic16_aopOp(left,ic,FALSE);
10294 pic16_aopOp(result,ic,TRUE);
10296 sign = !SPEC_USIGN(operandType (left));
10297 signedCount = !SPEC_USIGN(operandType (right));
10299 /* if the shift count is known then do it
10300 as efficiently as possible */
10301 if (AOP_TYPE(right) == AOP_LIT) {
10302 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10303 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10304 // we should modify right->aopu.aop_lit here!
10305 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10306 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10308 pic16_genLeftShiftLiteral (left,right,result,ic);
10310 genRightShiftLiteral (left,right,result,ic, sign);
10313 } // if (right is literal)
10315 /* shift count is unknown then we have to form a loop.
10316 * Note: we take only the lower order byte since shifting
10317 * more than 32 bits make no sense anyway, ( the
10318 * largest size of an object can be only 32 bits )
10319 * Note: we perform arithmetic shifts if the left operand is
10320 * signed and we do an (effective) right shift, i. e. we
10321 * shift in the sign bit from the left. */
10323 label_complete = newiTempLabel ( NULL );
10324 label_loop_pos = newiTempLabel ( NULL );
10325 label_loop_neg = NULL;
10326 label_negative = NULL;
10327 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10328 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10331 // additional labels needed
10332 label_loop_neg = newiTempLabel ( NULL );
10333 label_negative = newiTempLabel ( NULL );
10336 // copy source to result -- this will effectively truncate the left operand to the size of result!
10337 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10338 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10339 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10340 pic16_mov2f (AOP(result),AOP(left), offset);
10343 // if result is longer than left, fill with zeros (or sign)
10344 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10345 if (sign && AOP_SIZE(left) > 0) {
10346 // shift signed operand -- fill with sign
10347 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10348 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10349 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10350 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10351 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10354 // shift unsigned operand -- fill result with zeros
10355 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10356 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10359 } // if (size mismatch)
10361 pic16_mov2w (AOP(right), 0);
10362 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10363 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10366 // perform a shift by one (shift count is positive)
10367 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10368 // 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])
10369 pic16_emitpLabel (label_loop_pos->key);
10371 if (sign && (pos_shift == POC_RRCF)) {
10372 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10375 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10376 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10377 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10379 // perform a shift by one (shift count is positive)
10380 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10381 // 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])
10382 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10383 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10385 pic16_emitpLabel (label_loop_pos->key);
10386 if (sign && (pos_shift == POC_RRCF)) {
10387 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10390 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10391 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10392 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10393 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10397 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10399 pic16_emitpLabel (label_negative->key);
10400 // perform a shift by -1 (shift count is negative)
10401 // 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)
10403 pic16_emitpLabel (label_loop_neg->key);
10404 if (sign && (neg_shift == POC_RRCF)) {
10405 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10408 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10409 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10410 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10411 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10412 } // if (signedCount)
10414 pic16_emitpLabel (label_complete->key);
10417 pic16_freeAsmop (right,NULL,ic,TRUE);
10418 pic16_freeAsmop(left,NULL,ic,TRUE);
10419 pic16_freeAsmop(result,NULL,ic,TRUE);
10422 static void genLeftShift (iCode *ic) {
10423 genGenericShift (ic, 1);
10426 static void genRightShift (iCode *ic) {
10427 genGenericShift (ic, 0);
10432 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10433 void pic16_loadFSR0(operand *op, int lit)
10435 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10436 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10438 assert (!OP_SYMBOL(op)->remat);
10439 // set up FSR0 with address of result
10440 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10441 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10445 /*----------------------------------------------------------------*/
10446 /* pic16_derefPtr - move one byte from the location ptr points to */
10447 /* to WREG (doWrite == 0) or one byte from WREG */
10448 /* to the location ptr points to (doWrite != 0) */
10449 /*----------------------------------------------------------------*/
10450 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10455 if (!fsr0_setup || !*fsr0_setup)
10457 pic16_loadFSR0( ptr, 0 );
10458 if (fsr0_setup) *fsr0_setup = 1;
10461 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10463 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10467 if (AOP(ptr)->aopu.aop_reg[2]) {
10468 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10469 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10470 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10471 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl)));
10472 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(ptr),2));
10473 pic16_callGenericPointerRW(doWrite, 1);
10475 // data pointer (just 2 byte given)
10476 if (!fsr0_setup || !*fsr0_setup)
10478 pic16_loadFSR0( ptr, 0 );
10479 if (fsr0_setup) *fsr0_setup = 1;
10482 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10484 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10489 assert (0 && "invalid pointer type specified");
10494 /*-----------------------------------------------------------------*/
10495 /* genUnpackBits - generates code for unpacking bits */
10496 /*-----------------------------------------------------------------*/
10497 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10500 sym_link *etype, *letype;
10501 int blen=0, bstr=0;
10504 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10505 etype = getSpec(operandType(result));
10506 letype = getSpec(operandType(left));
10508 // if(IS_BITFIELD(etype)) {
10509 blen = SPEC_BLEN(etype);
10510 bstr = SPEC_BSTR(etype);
10513 lbstr = SPEC_BSTR( letype );
10515 DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10516 SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10519 if((blen == 1) && (bstr < 8)) {
10520 /* it is a single bit, so use the appropriate bit instructions */
10521 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10523 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10525 // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10526 if(!IS_PTR(operandType(left))/* && OP_SYMBOL(left)->remat && (ptype == POINTER)*/) {
10527 /* workaround to reduce the extra lfsr instruction */
10528 pic16_emitpcode(POC_BTFSC,
10529 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10531 /* this code does only handle __data pointers correctly */
10532 assert (IS_DATA_PTR(operandType(left)));
10533 pic16_loadFSR0 (left, 0);
10534 pic16_emitpcode(POC_BTFSC,
10535 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10538 if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10539 /* unsigned bitfields result in either 0 or 1 */
10540 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10542 /* signed bitfields result in either 0 or -1 */
10543 pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_wreg));
10545 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10547 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10553 /* the following call to pic16_loadFSR0 is temporary until
10554 * optimization to handle single bit assignments is added
10555 * to the function. Until then use the old safe way! -- VR */
10557 if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
10558 // access symbol directly
10559 pic16_mov2w (AOP(left), 0);
10561 pic16_derefPtr (left, ptype, 0, NULL);
10564 /* if we have bitdisplacement then it fits */
10565 /* into this byte completely or if length is */
10566 /* less than a byte */
10567 if ((shCnt = SPEC_BSTR(etype)) ||
10568 (SPEC_BLEN(etype) <= 8)) {
10570 /* shift right acc */
10573 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10574 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10576 /* VR -- normally I would use the following, but since we use the hack,
10577 * to avoid the masking from AccRsh, why not mask it right now? */
10580 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10583 /* extend signed bitfields to 8 bits */
10584 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10586 assert (blen + bstr > 0);
10587 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10588 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10591 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10593 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10599 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10600 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10607 static void genDataPointerGet(operand *left,
10611 int size, offset = 0, leoffset=0 ;
10613 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10614 pic16_aopOp(result, ic, TRUE);
10618 size = AOP_SIZE(result);
10619 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10623 /* The following tests may save a redudant movff instruction when
10624 * accessing unions */
10626 /* if they are the same */
10627 if (operandsEqu (left, result)) {
10628 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10634 /* if they are the same registers */
10635 if (pic16_sameRegs(AOP(left),AOP(result))) {
10636 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10642 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10643 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10644 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10651 if ( AOP_TYPE(left) == AOP_PCODE) {
10652 fprintf(stderr,"genDataPointerGet %s, %d\n",
10653 AOP(left)->aopu.pcop->name,
10654 (AOP(left)->aopu.pcop->type == PO_DIR)?
10655 PCOR(AOP(left)->aopu.pcop)->instance:
10656 PCOI(AOP(left)->aopu.pcop)->offset);
10660 if(AOP(left)->aopu.pcop->type == PO_DIR)
10661 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10663 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10666 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10668 // pic16_DumpOp("(result)",result);
10669 if(is_LitAOp(AOP(result))) {
10670 pic16_mov2w(AOP(left), offset); // patch 8
10671 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10673 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10674 pic16_popGet(AOP(left), offset), //patch 8
10675 pic16_popGet(AOP(result), offset)));
10683 pic16_freeAsmop(result,NULL,ic,TRUE);
10688 /*-----------------------------------------------------------------*/
10689 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10690 /*-----------------------------------------------------------------*/
10691 static void genNearPointerGet (operand *left,
10695 // asmop *aop = NULL;
10696 //regs *preg = NULL ;
10697 sym_link *rtype, *retype;
10698 sym_link *ltype, *letype;
10702 rtype = operandType(result);
10703 retype= getSpec(rtype);
10704 ltype = operandType(left);
10705 letype= getSpec(ltype);
10707 pic16_aopOp(left,ic,FALSE);
10709 // pic16_DumpOp("(left)",left);
10710 // pic16_DumpOp("(result)",result);
10712 /* if left is rematerialisable and
10713 * result is not bit variable type and
10714 * the left is pointer to data space i.e
10715 * lower 128 bytes of space */
10717 if (AOP_TYPE(left) == AOP_PCODE
10718 && !IS_BITFIELD(retype)
10719 && DCL_TYPE(ltype) == POINTER) {
10721 genDataPointerGet (left,result,ic);
10722 pic16_freeAsmop(left, NULL, ic, TRUE);
10726 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10727 pic16_aopOp (result,ic,TRUE);
10729 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10732 if(IS_BITFIELD( retype )
10733 && (SPEC_BLEN(operandType(result))==1)
10737 int bitstrt, bytestrt;
10739 /* if this is bitfield of size 1, see if we are checking the value
10740 * of a single bit in an if-statement,
10741 * if yes, then don't generate usual code, but execute the
10742 * genIfx directly -- VR */
10746 /* CHECK: if next iCode is IFX
10747 * and current result operand is nextic's conditional operand
10748 * and current result operand live ranges ends at nextic's key number
10750 if((nextic->op == IFX)
10751 && (result == IC_COND(nextic))
10752 && (OP_LIVETO(result) == nextic->seq)
10753 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10755 /* everything is ok then */
10756 /* find a way to optimize the genIfx iCode */
10758 bytestrt = SPEC_BSTR(operandType(result))/8;
10759 bitstrt = SPEC_BSTR(operandType(result))%8;
10761 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10763 genIfxpCOpJump(nextic, jop);
10765 pic16_freeAsmop(left, NULL, ic, TRUE);
10766 pic16_freeAsmop(result, NULL, ic, TRUE);
10772 /* if bitfield then unpack the bits */
10773 if (IS_BITFIELD(letype))
10774 genUnpackBits (result, left, NULL, POINTER);
10776 /* we have can just get the values */
10777 int size = AOP_SIZE(result);
10780 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10782 pic16_loadFSR0( left, 0 );
10786 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10787 pic16_popGet(AOP(result), offset++)));
10789 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10790 pic16_popGet(AOP(result), offset++)));
10796 /* now some housekeeping stuff */
10798 /* we had to allocate for this iCode */
10799 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10800 pic16_freeAsmop(NULL,aop,ic,TRUE);
10802 /* we did not allocate which means left
10803 * already in a pointer register, then
10804 * if size > 0 && this could be used again
10805 * we have to point it back to where it
10807 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10808 if (AOP_SIZE(result) > 1
10809 && !OP_SYMBOL(left)->remat
10810 && ( OP_SYMBOL(left)->liveTo > ic->seq
10812 // int size = AOP_SIZE(result) - 1;
10814 // pic16_emitcode("dec","%s",rname);
10820 pic16_freeAsmop(left,NULL,ic,TRUE);
10821 pic16_freeAsmop(result,NULL,ic,TRUE);
10824 /*-----------------------------------------------------------------*/
10825 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10826 /*-----------------------------------------------------------------*/
10827 static void genPagedPointerGet (operand *left,
10832 regs *preg = NULL ;
10834 sym_link *rtype, *retype;
10836 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10838 rtype = operandType(result);
10839 retype= getSpec(rtype);
10841 pic16_aopOp(left,ic,FALSE);
10843 /* if the value is already in a pointer register
10844 then don't need anything more */
10845 if (!AOP_INPREG(AOP(left))) {
10846 /* otherwise get a free pointer register */
10848 preg = getFreePtr(ic,&aop,FALSE);
10849 pic16_emitcode("mov","%s,%s",
10851 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10852 rname = preg->name ;
10854 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10856 pic16_freeAsmop(left,NULL,ic,TRUE);
10857 pic16_aopOp (result,ic,TRUE);
10859 /* if bitfield then unpack the bits */
10860 if (IS_BITFIELD(retype))
10861 genUnpackBits (result,left,rname,PPOINTER);
10863 /* we have can just get the values */
10864 int size = AOP_SIZE(result);
10869 pic16_emitcode("movx","a,@%s",rname);
10870 pic16_aopPut(AOP(result),"a",offset);
10875 pic16_emitcode("inc","%s",rname);
10879 /* now some housekeeping stuff */
10881 /* we had to allocate for this iCode */
10882 pic16_freeAsmop(NULL,aop,ic,TRUE);
10884 /* we did not allocate which means left
10885 already in a pointer register, then
10886 if size > 0 && this could be used again
10887 we have to point it back to where it
10889 if (AOP_SIZE(result) > 1 &&
10890 !OP_SYMBOL(left)->remat &&
10891 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10893 int size = AOP_SIZE(result) - 1;
10895 pic16_emitcode("dec","%s",rname);
10900 pic16_freeAsmop(result,NULL,ic,TRUE);
10906 /* This code is not adjusted to PIC16 and fails utterly.
10907 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10909 /*-----------------------------------------------------------------*/
10910 /* genFarPointerGet - gget value from far space */
10911 /*-----------------------------------------------------------------*/
10912 static void genFarPointerGet (operand *left,
10913 operand *result, iCode *ic)
10916 sym_link *retype = getSpec(operandType(result));
10918 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10920 pic16_aopOp(left,ic,FALSE);
10922 /* if the operand is already in dptr
10923 then we do nothing else we move the value to dptr */
10924 if (AOP_TYPE(left) != AOP_STR) {
10925 /* if this is remateriazable */
10926 if (AOP_TYPE(left) == AOP_IMMD)
10927 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10928 else { /* we need to get it byte by byte */
10929 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10930 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10931 if (options.model == MODEL_FLAT24)
10933 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10937 /* so dptr know contains the address */
10938 pic16_freeAsmop(left,NULL,ic,TRUE);
10939 pic16_aopOp(result,ic,TRUE);
10941 /* if bit then unpack */
10942 if (IS_BITFIELD(retype))
10943 genUnpackBits(result,left,"dptr",FPOINTER);
10945 size = AOP_SIZE(result);
10949 pic16_emitcode("movx","a,@dptr");
10950 pic16_aopPut(AOP(result),"a",offset++);
10952 pic16_emitcode("inc","dptr");
10956 pic16_freeAsmop(result,NULL,ic,TRUE);
10961 /*-----------------------------------------------------------------*/
10962 /* genCodePointerGet - get value from code space */
10963 /*-----------------------------------------------------------------*/
10964 static void genCodePointerGet (operand *left,
10965 operand *result, iCode *ic)
10968 sym_link *retype = getSpec(operandType(result));
10970 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10972 pic16_aopOp(left,ic,FALSE);
10974 /* if the operand is already in dptr
10975 then we do nothing else we move the value to dptr */
10976 if (AOP_TYPE(left) != AOP_STR) {
10977 /* if this is remateriazable */
10978 if (AOP_TYPE(left) == AOP_IMMD)
10979 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10980 else { /* we need to get it byte by byte */
10981 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10982 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10983 if (options.model == MODEL_FLAT24)
10985 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10989 /* so dptr know contains the address */
10990 pic16_freeAsmop(left,NULL,ic,TRUE);
10991 pic16_aopOp(result,ic,FALSE);
10993 /* if bit then unpack */
10994 if (IS_BITFIELD(retype))
10995 genUnpackBits(result,left,"dptr",CPOINTER);
10997 size = AOP_SIZE(result);
11001 pic16_emitcode("clr","a");
11002 pic16_emitcode("movc","a,@a+dptr");
11003 pic16_aopPut(AOP(result),"a",offset++);
11005 pic16_emitcode("inc","dptr");
11009 pic16_freeAsmop(result,NULL,ic,TRUE);
11014 /*-----------------------------------------------------------------*/
11015 /* genGenPointerGet - gget value from generic pointer space */
11016 /*-----------------------------------------------------------------*/
11017 static void genGenPointerGet (operand *left,
11018 operand *result, iCode *ic)
11020 int size, offset, lit;
11021 sym_link *retype = getSpec(operandType(result));
11023 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11024 pic16_aopOp(left,ic,FALSE);
11025 pic16_aopOp(result,ic,FALSE);
11026 size = AOP_SIZE(result);
11028 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11030 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11032 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11033 // load FSR0 from immediate
11034 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11036 // pic16_loadFSR0( left );
11041 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11043 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11050 else { /* we need to get it byte by byte */
11051 // set up FSR0 with address from left
11052 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11053 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11059 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11061 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11068 /* if bit then unpack */
11069 if (IS_BITFIELD(retype))
11070 genUnpackBits(result,left,"BAD",GPOINTER);
11073 pic16_freeAsmop(left,NULL,ic,TRUE);
11074 pic16_freeAsmop(result,NULL,ic,TRUE);
11080 /*-----------------------------------------------------------------*/
11081 /* genGenPointerGet - gget value from generic pointer space */
11082 /*-----------------------------------------------------------------*/
11083 static void genGenPointerGet (operand *left,
11084 operand *result, iCode *ic)
11086 int size, offset, lit;
11087 sym_link *letype = getSpec(operandType(left));
11089 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11090 pic16_aopOp(left,ic,FALSE);
11091 pic16_aopOp(result,ic,TRUE);
11092 size = AOP_SIZE(result);
11094 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11096 /* if bit then unpack */
11097 if (IS_BITFIELD(letype)) {
11098 genUnpackBits(result,left,"BAD",GPOINTER);
11102 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11104 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11105 // load FSR0 from immediate
11106 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11108 werror(W_POSSBUG2, __FILE__, __LINE__);
11113 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11115 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11122 } else { /* we need to get it byte by byte */
11124 /* set up WREG:PRODL:FSR0L with address from left */
11125 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11126 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11127 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11129 pic16_callGenericPointerRW(0, size);
11131 assignResultValue(result, 1);
11137 pic16_freeAsmop(left,NULL,ic,TRUE);
11138 pic16_freeAsmop(result,NULL,ic,TRUE);
11141 /*-----------------------------------------------------------------*/
11142 /* genConstPointerGet - get value from const generic pointer space */
11143 /*-----------------------------------------------------------------*/
11144 static void genConstPointerGet (operand *left,
11145 operand *result, iCode *ic)
11147 //sym_link *retype = getSpec(operandType(result));
11148 // symbol *albl = newiTempLabel(NULL); // patch 15
11149 // symbol *blbl = newiTempLabel(NULL); //
11150 // PIC_OPCODE poc; // patch 15
11154 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11155 pic16_aopOp(left,ic,FALSE);
11156 pic16_aopOp(result,ic,TRUE);
11157 size = AOP_SIZE(result);
11159 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11161 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11163 // set up table pointer
11164 if( (AOP_TYPE(left) == AOP_PCODE)
11165 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11166 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11168 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11169 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11170 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11171 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11172 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11173 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11175 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11176 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11177 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11181 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11182 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11186 pic16_freeAsmop(left,NULL,ic,TRUE);
11187 pic16_freeAsmop(result,NULL,ic,TRUE);
11191 /*-----------------------------------------------------------------*/
11192 /* genPointerGet - generate code for pointer get */
11193 /*-----------------------------------------------------------------*/
11194 static void genPointerGet (iCode *ic)
11196 operand *left, *result ;
11197 sym_link *type, *etype;
11202 left = IC_LEFT(ic);
11203 result = IC_RESULT(ic) ;
11205 /* depending on the type of pointer we need to
11206 move it to the correct pointer register */
11207 type = operandType(left);
11208 etype = getSpec(type);
11211 if (IS_PTR_CONST(type))
11213 if (IS_CODEPTR(type))
11215 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11217 /* if left is of type of pointer then it is simple */
11218 if (IS_PTR(type) && !IS_FUNC(type->next))
11219 p_type = DCL_TYPE(type);
11221 /* we have to go by the storage class */
11222 p_type = PTR_TYPE(SPEC_OCLS(etype));
11224 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11226 if (SPEC_OCLS(etype)->codesp ) {
11227 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11228 //p_type = CPOINTER ;
11230 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11231 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11232 /*p_type = FPOINTER ;*/
11234 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11235 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11236 /* p_type = PPOINTER; */
11238 if (SPEC_OCLS(etype) == idata ) {
11239 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11240 /* p_type = IPOINTER; */
11242 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11243 /* p_type = POINTER ; */
11247 /* now that we have the pointer type we assign
11248 the pointer values */
11253 genNearPointerGet (left,result,ic);
11257 genPagedPointerGet(left,result,ic);
11261 /* PICs do not support FAR pointers... */
11262 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11264 genFarPointerGet (left,result,ic);
11269 genConstPointerGet (left,result,ic);
11270 //pic16_emitcodePointerGet (left,result,ic);
11275 if (IS_PTR_CONST(type))
11276 genConstPointerGet (left,result,ic);
11279 genGenPointerGet (left,result,ic);
11283 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11284 "genPointerGet: illegal pointer type");
11289 /*-----------------------------------------------------------------*/
11290 /* genPackBits - generates code for packed bit storage */
11291 /*-----------------------------------------------------------------*/
11292 static void genPackBits (sym_link *etype , operand *result,
11294 char *rname, int p_type)
11302 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11303 blen = SPEC_BLEN(etype);
11304 bstr = SPEC_BSTR(etype);
11306 retype = getSpec(operandType(right));
11308 if(AOP_TYPE(right) == AOP_LIT) {
11309 if((blen == 1) && (bstr < 8)) {
11311 /* it is a single bit, so use the appropriate bit instructions */
11313 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11315 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11316 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11317 if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11318 /* workaround to reduce the extra lfsr instruction */
11320 pic16_emitpcode(POC_BSF,
11321 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11323 pic16_emitpcode(POC_BCF,
11324 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11327 pic16_loadFSR0(result, 0);
11329 pic16_emitpcode(POC_BSF,
11330 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11332 pic16_emitpcode(POC_BCF,
11333 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11339 /* move literal to W */
11340 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11343 if(IS_BITFIELD(retype)
11344 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11348 rblen = SPEC_BLEN( retype );
11349 rbstr = SPEC_BSTR( retype );
11352 if(IS_BITFIELD(etype)) {
11353 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11354 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11356 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11359 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11361 if(IS_BITFIELD(etype)) {
11362 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11364 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11367 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11371 /* move right to W */
11372 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11375 /* if the bit length is less than or */
11376 /* it exactly fits a byte then */
11377 if((shCnt=SPEC_BSTR(etype))
11378 || SPEC_BLEN(etype) <= 8 ) {
11379 int fsr0_setup = 0;
11381 if (blen != 8 || bstr != 0) {
11382 // we need to combine the value with the old value
11383 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11385 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11386 SPEC_BSTR(etype), SPEC_BLEN(etype));
11388 /* shift left acc */
11391 /* using PRODH as a temporary register here */
11392 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11394 if (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) {
11395 /* access symbol directly */
11396 pic16_mov2w (AOP(result), 0);
11398 /* get old value */
11399 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11402 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11403 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11404 (unsigned char)(0xff >> (8-bstr))) ));
11405 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11406 } // if (blen != 8 || bstr != 0)
11408 /* write new value back */
11409 if (IS_SYMOP(result) & !IS_PTR(operandType(result))) {
11410 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11412 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11421 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11422 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11427 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11428 rLen = SPEC_BLEN(etype)-8;
11430 /* now generate for lengths greater than one byte */
11434 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11440 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11446 pic16_emitcode("movx","@dptr,a");
11451 DEBUGpic16_emitcode(";lcall","__gptrput");
11459 pic16_mov2w(AOP(right), offset++);
11462 /* last last was not complete */
11464 /* save the byte & read byte */
11467 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11468 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11473 pic16_emitcode ("mov","b,a");
11474 pic16_emitcode("movx","a,@dptr");
11478 pic16_emitcode ("push","b");
11479 pic16_emitcode ("push","acc");
11480 pic16_emitcode ("lcall","__gptrget");
11481 pic16_emitcode ("pop","b");
11487 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11488 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11489 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11490 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11491 // pic16_emitcode ("orl","a,b");
11494 // if (p_type == GPOINTER)
11495 // pic16_emitcode("pop","b");
11500 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11501 // pic16_emitcode("mov","@%s,a",rname);
11505 pic16_emitcode("movx","@dptr,a");
11509 DEBUGpic16_emitcode(";lcall","__gptrput");
11516 // pic16_freeAsmop(right, NULL, ic, TRUE);
11518 /*-----------------------------------------------------------------*/
11519 /* genDataPointerSet - remat pointer to data space */
11520 /*-----------------------------------------------------------------*/
11521 static void genDataPointerSet(operand *right,
11525 int size, offset = 0, resoffset=0 ;
11527 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11528 pic16_aopOp(right,ic,FALSE);
11530 size = AOP_SIZE(right);
11532 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11535 if ( AOP_TYPE(result) == AOP_PCODE) {
11536 fprintf(stderr,"genDataPointerSet %s, %d\n",
11537 AOP(result)->aopu.pcop->name,
11538 (AOP(result)->aopu.pcop->type == PO_DIR)?
11539 PCOR(AOP(result)->aopu.pcop)->instance:
11540 PCOI(AOP(result)->aopu.pcop)->offset);
11544 if(AOP(result)->aopu.pcop->type == PO_DIR)
11545 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11548 if (AOP_TYPE(right) == AOP_LIT) {
11551 if(!IS_FLOAT(operandType( right )))
11552 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11555 unsigned long lit_int;
11559 /* take care if literal is a float */
11560 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11561 lit = info.lit_int;
11564 lit = lit >> (8*offset);
11566 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11567 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11569 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11572 pic16_mov2w(AOP(right), offset);
11573 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11579 pic16_freeAsmop(right,NULL,ic,TRUE);
11584 /*-----------------------------------------------------------------*/
11585 /* genNearPointerSet - pic16_emitcode for near pointer put */
11586 /*-----------------------------------------------------------------*/
11587 static void genNearPointerSet (operand *right,
11593 sym_link *ptype = operandType(result);
11594 sym_link *resetype;
11596 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11597 retype= getSpec(operandType(right));
11598 resetype = getSpec(operandType(result));
11600 pic16_aopOp(result,ic,FALSE);
11602 /* if the result is rematerializable &
11603 * in data space & not a bit variable */
11605 /* and result is not a bit variable */
11606 if (AOP_TYPE(result) == AOP_PCODE
11607 // && AOP_TYPE(result) == AOP_IMMD
11608 && DCL_TYPE(ptype) == POINTER
11609 && !IS_BITFIELD(retype)
11610 && !IS_BITFIELD(resetype)) {
11612 genDataPointerSet (right,result,ic);
11613 pic16_freeAsmop(result,NULL,ic,TRUE);
11617 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11618 pic16_aopOp(right,ic,FALSE);
11619 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11621 /* if bitfield then unpack the bits */
11622 if (IS_BITFIELD(resetype)) {
11623 genPackBits (resetype, result, right, NULL, POINTER);
11625 /* we have can just get the values */
11626 int size = AOP_SIZE(right);
11629 pic16_loadFSR0(result, 0);
11631 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11633 if (AOP_TYPE(right) == AOP_LIT) {
11634 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11636 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11638 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11640 } else { // no literal
11642 pic16_emitpcode(POC_MOVFF,
11643 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11644 pic16_popCopyReg(&pic16_pc_postinc0)));
11646 pic16_emitpcode(POC_MOVFF,
11647 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11648 pic16_popCopyReg(&pic16_pc_indf0)));
11655 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11656 /* now some housekeeping stuff */
11658 /* we had to allocate for this iCode */
11659 pic16_freeAsmop(NULL,aop,ic,TRUE);
11661 /* we did not allocate which means left
11662 * already in a pointer register, then
11663 * if size > 0 && this could be used again
11664 * we have to point it back to where it
11666 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11667 if (AOP_SIZE(right) > 1
11668 && !OP_SYMBOL(result)->remat
11669 && ( OP_SYMBOL(result)->liveTo > ic->seq
11672 int size = AOP_SIZE(right) - 1;
11675 pic16_emitcode("decf","fsr0,f");
11676 //pic16_emitcode("dec","%s",rname);
11680 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11683 pic16_freeAsmop(right,NULL,ic,TRUE);
11684 pic16_freeAsmop(result,NULL,ic,TRUE);
11687 /*-----------------------------------------------------------------*/
11688 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11689 /*-----------------------------------------------------------------*/
11690 static void genPagedPointerSet (operand *right,
11695 regs *preg = NULL ;
11699 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11701 retype= getSpec(operandType(right));
11703 pic16_aopOp(result,ic,FALSE);
11705 /* if the value is already in a pointer register
11706 then don't need anything more */
11707 if (!AOP_INPREG(AOP(result))) {
11708 /* otherwise get a free pointer register */
11710 preg = getFreePtr(ic,&aop,FALSE);
11711 pic16_emitcode("mov","%s,%s",
11713 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11714 rname = preg->name ;
11716 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11718 pic16_freeAsmop(result,NULL,ic,TRUE);
11719 pic16_aopOp (right,ic,FALSE);
11721 /* if bitfield then unpack the bits */
11722 if (IS_BITFIELD(retype))
11723 genPackBits (retype,result,right,rname,PPOINTER);
11725 /* we have can just get the values */
11726 int size = AOP_SIZE(right);
11730 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11733 pic16_emitcode("movx","@%s,a",rname);
11736 pic16_emitcode("inc","%s",rname);
11742 /* now some housekeeping stuff */
11744 /* we had to allocate for this iCode */
11745 pic16_freeAsmop(NULL,aop,ic,TRUE);
11747 /* we did not allocate which means left
11748 already in a pointer register, then
11749 if size > 0 && this could be used again
11750 we have to point it back to where it
11752 if (AOP_SIZE(right) > 1 &&
11753 !OP_SYMBOL(result)->remat &&
11754 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11756 int size = AOP_SIZE(right) - 1;
11758 pic16_emitcode("dec","%s",rname);
11763 pic16_freeAsmop(right,NULL,ic,TRUE);
11769 /* This code is not adjusted to PIC16 and fails utterly...
11770 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11772 /*-----------------------------------------------------------------*/
11773 /* genFarPointerSet - set value from far space */
11774 /*-----------------------------------------------------------------*/
11775 static void genFarPointerSet (operand *right,
11776 operand *result, iCode *ic)
11779 sym_link *retype = getSpec(operandType(right));
11781 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11782 pic16_aopOp(result,ic,FALSE);
11784 /* if the operand is already in dptr
11785 then we do nothing else we move the value to dptr */
11786 if (AOP_TYPE(result) != AOP_STR) {
11787 /* if this is remateriazable */
11788 if (AOP_TYPE(result) == AOP_IMMD)
11789 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11790 else { /* we need to get it byte by byte */
11791 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11792 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11793 if (options.model == MODEL_FLAT24)
11795 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11799 /* so dptr know contains the address */
11800 pic16_freeAsmop(result,NULL,ic,TRUE);
11801 pic16_aopOp(right,ic,FALSE);
11803 /* if bit then unpack */
11804 if (IS_BITFIELD(retype))
11805 genPackBits(retype,result,right,"dptr",FPOINTER);
11807 size = AOP_SIZE(right);
11811 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11813 pic16_emitcode("movx","@dptr,a");
11815 pic16_emitcode("inc","dptr");
11819 pic16_freeAsmop(right,NULL,ic,TRUE);
11823 /*-----------------------------------------------------------------*/
11824 /* genGenPointerSet - set value from generic pointer space */
11825 /*-----------------------------------------------------------------*/
11827 static void genGenPointerSet (operand *right,
11828 operand *result, iCode *ic)
11830 int i, size, offset, lit;
11831 sym_link *retype = getSpec(operandType(right));
11833 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11835 pic16_aopOp(result,ic,FALSE);
11836 pic16_aopOp(right,ic,FALSE);
11837 size = AOP_SIZE(right);
11840 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11842 /* if the operand is already in dptr
11843 then we do nothing else we move the value to dptr */
11844 if (AOP_TYPE(result) != AOP_STR) {
11845 /* if this is remateriazable */
11846 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11847 // WARNING: anythig until "else" is untested!
11848 if (AOP_TYPE(result) == AOP_IMMD) {
11849 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11850 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11851 // load FSR0 from immediate
11852 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11856 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11858 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11864 else { /* we need to get it byte by byte */
11865 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11866 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11868 // set up FSR0 with address of result
11869 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11870 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11872 /* hack hack! see if this the FSR. If so don't load W */
11873 if(AOP_TYPE(right) != AOP_ACC) {
11875 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11877 if(AOP_TYPE(right) == AOP_LIT)
11880 // note: pic16_popGet handles sign extension
11881 for(i=0;i<size;i++) {
11882 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11884 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11886 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11891 for(i=0;i<size;i++) {
11893 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11894 pic16_popCopyReg(&pic16_pc_postinc0)));
11896 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11897 pic16_popCopyReg(&pic16_pc_indf0)));
11903 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11904 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11906 } // if (AOP_TYPE(result) != AOP_IMMD)
11908 } // if (AOP_TYPE(result) != AOP_STR)
11909 /* so dptr know contains the address */
11912 /* if bit then unpack */
11913 if (IS_BITFIELD(retype))
11914 genPackBits(retype,result,right,"dptr",GPOINTER);
11916 size = AOP_SIZE(right);
11919 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11921 // set up FSR0 with address of result
11922 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11923 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11926 if (AOP_TYPE(right) == AOP_LIT) {
11927 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11929 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11931 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11933 } else { // no literal
11935 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11937 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11945 pic16_freeAsmop(right,NULL,ic,TRUE);
11946 pic16_freeAsmop(result,NULL,ic,TRUE);
11950 static void genGenPointerSet (operand *right,
11951 operand *result, iCode *ic)
11954 sym_link *retype = getSpec(operandType(result));
11956 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11958 pic16_aopOp(result,ic,FALSE);
11959 pic16_aopOp(right,ic,FALSE);
11960 size = AOP_SIZE(right);
11962 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11965 /* if bit then unpack */
11966 if (IS_BITFIELD(retype)) {
11967 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11968 genPackBits(retype,result,right,"dptr",GPOINTER);
11972 size = AOP_SIZE(right);
11974 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11977 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11979 /* value of right+0 is placed on stack, which will be retrieved
11980 * by the support function this restoring the stack. The important
11981 * thing is that there is no need to manually restore stack pointer
11983 pushaop(AOP(right), 0);
11984 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11985 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11986 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11987 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
11989 /* load address to write to in WREG:FSR0H:FSR0L */
11990 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
11991 pic16_popCopyReg(&pic16_pc_fsr0l)));
11992 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
11993 pic16_popCopyReg(&pic16_pc_prodl)));
11994 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
11996 pic16_callGenericPointerRW(1, size);
11999 pic16_freeAsmop(right,NULL,ic,TRUE);
12000 pic16_freeAsmop(result,NULL,ic,TRUE);
12003 /*-----------------------------------------------------------------*/
12004 /* genPointerSet - stores the value into a pointer location */
12005 /*-----------------------------------------------------------------*/
12006 static void genPointerSet (iCode *ic)
12008 operand *right, *result ;
12009 sym_link *type, *etype;
12014 right = IC_RIGHT(ic);
12015 result = IC_RESULT(ic) ;
12017 /* depending on the type of pointer we need to
12018 move it to the correct pointer register */
12019 type = operandType(result);
12020 etype = getSpec(type);
12022 /* if left is of type of pointer then it is simple */
12023 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12024 p_type = DCL_TYPE(type);
12027 /* we have to go by the storage class */
12028 p_type = PTR_TYPE(SPEC_OCLS(etype));
12030 /* if (SPEC_OCLS(etype)->codesp ) { */
12031 /* p_type = CPOINTER ; */
12034 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12035 /* p_type = FPOINTER ; */
12037 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12038 /* p_type = PPOINTER ; */
12040 /* if (SPEC_OCLS(etype) == idata ) */
12041 /* p_type = IPOINTER ; */
12043 /* p_type = POINTER ; */
12046 /* now that we have the pointer type we assign
12047 the pointer values */
12052 genNearPointerSet (right,result,ic);
12056 genPagedPointerSet (right,result,ic);
12060 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12062 genFarPointerSet (right,result,ic);
12067 genGenPointerSet (right,result,ic);
12071 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12072 "genPointerSet: illegal pointer type");
12076 /*-----------------------------------------------------------------*/
12077 /* genIfx - generate code for Ifx statement */
12078 /*-----------------------------------------------------------------*/
12079 static void genIfx (iCode *ic, iCode *popIc)
12081 operand *cond = IC_COND(ic);
12086 pic16_aopOp(cond,ic,FALSE);
12088 /* get the value into acc */
12089 if (AOP_TYPE(cond) != AOP_CRY)
12090 pic16_toBoolean(cond);
12093 /* the result is now in the accumulator */
12094 pic16_freeAsmop(cond,NULL,ic,TRUE);
12096 /* if there was something to be popped then do it */
12100 /* if the condition is a bit variable */
12101 if (isbit && IS_ITEMP(cond) &&
12103 genIfxJump(ic,"c");
12104 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12106 if (isbit && !IS_ITEMP(cond))
12107 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12109 genIfxJump(ic,"a");
12114 /*-----------------------------------------------------------------*/
12115 /* genAddrOf - generates code for address of */
12116 /*-----------------------------------------------------------------*/
12117 static void genAddrOf (iCode *ic)
12119 operand *result, *left;
12121 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12122 pCodeOp *pcop0, *pcop1, *pcop2;
12126 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12128 sym = OP_SYMBOL( IC_LEFT(ic) );
12131 /* get address of symbol on stack */
12132 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12134 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12135 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12138 // operands on stack are accessible via "FSR2 + index" with index
12139 // starting at 2 for arguments and growing from 0 downwards for
12140 // local variables (index == 0 is not assigned so we add one here)
12142 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12144 assert (soffs < 0);
12147 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12148 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12149 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12150 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12151 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12152 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12153 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12159 // if(pic16_debug_verbose) {
12160 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12161 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12164 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12165 size = AOP_SIZE(IC_RESULT(ic));
12167 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12168 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12169 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12172 pic16_emitpcode(POC_MOVLW, pcop0);
12173 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12174 pic16_emitpcode(POC_MOVLW, pcop1);
12175 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12176 pic16_emitpcode(POC_MOVLW, pcop2);
12177 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12180 pic16_emitpcode(POC_MOVLW, pcop0);
12181 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12182 pic16_emitpcode(POC_MOVLW, pcop1);
12183 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12185 pic16_emitpcode(POC_MOVLW, pcop0);
12186 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12189 pic16_freeAsmop(left, NULL, ic, FALSE);
12191 pic16_freeAsmop(result,NULL,ic,TRUE);
12196 /*-----------------------------------------------------------------*/
12197 /* genFarFarAssign - assignment when both are in far space */
12198 /*-----------------------------------------------------------------*/
12199 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12201 int size = AOP_SIZE(right);
12204 /* first push the right side on to the stack */
12206 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12208 pic16_emitcode ("push","acc");
12211 pic16_freeAsmop(right,NULL,ic,FALSE);
12212 /* now assign DPTR to result */
12213 pic16_aopOp(result,ic,FALSE);
12214 size = AOP_SIZE(result);
12216 pic16_emitcode ("pop","acc");
12217 pic16_aopPut(AOP(result),"a",--offset);
12219 pic16_freeAsmop(result,NULL,ic,FALSE);
12224 /*-----------------------------------------------------------------*/
12225 /* genAssign - generate code for assignment */
12226 /*-----------------------------------------------------------------*/
12227 static void genAssign (iCode *ic)
12229 operand *result, *right;
12230 int size, offset,know_W;
12231 unsigned long lit = 0L;
12233 result = IC_RESULT(ic);
12234 right = IC_RIGHT(ic) ;
12238 /* if they are the same */
12239 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12242 /* reversed order operands are aopOp'ed so that result operand
12243 * is effective in case right is a stack symbol. This maneauver
12244 * allows to use the _G.resDirect flag later */
12245 pic16_aopOp(result,ic,TRUE);
12246 pic16_aopOp(right,ic,FALSE);
12248 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12250 /* if they are the same registers */
12251 if (pic16_sameRegs(AOP(right),AOP(result)))
12254 /* if the result is a bit */
12255 if (AOP_TYPE(result) == AOP_CRY) {
12256 /* if the right size is a literal then
12257 we know what the value is */
12258 if (AOP_TYPE(right) == AOP_LIT) {
12260 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12261 pic16_popGet(AOP(result),0));
12263 if (((int) operandLitValue(right)))
12264 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12265 AOP(result)->aopu.aop_dir,
12266 AOP(result)->aopu.aop_dir);
12268 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12269 AOP(result)->aopu.aop_dir,
12270 AOP(result)->aopu.aop_dir);
12274 /* the right is also a bit variable */
12275 if (AOP_TYPE(right) == AOP_CRY) {
12276 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12277 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12278 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12280 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12281 AOP(result)->aopu.aop_dir,
12282 AOP(result)->aopu.aop_dir);
12283 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12284 AOP(right)->aopu.aop_dir,
12285 AOP(right)->aopu.aop_dir);
12286 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12287 AOP(result)->aopu.aop_dir,
12288 AOP(result)->aopu.aop_dir);
12292 /* we need to or */
12293 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12294 pic16_toBoolean(right);
12296 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12297 //pic16_aopPut(AOP(result),"a",0);
12301 /* bit variables done */
12303 size = AOP_SIZE(result);
12306 if(AOP_TYPE(right) == AOP_LIT) {
12307 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12308 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12311 unsigned long lit_int;
12316 if(IS_FIXED16X16(operandType(right))) {
12317 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12319 /* take care if literal is a float */
12320 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12321 lit = info.lit_int;
12326 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12327 // sizeof(unsigned long int), sizeof(float));
12330 if (AOP_TYPE(right) == AOP_REG) {
12331 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12333 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12338 /* when do we have to read the program memory?
12339 * - if right itself is a symbol in code space
12340 * (we don't care what it points to if it's a pointer)
12341 * - AND right is not a function (we would want its address)
12343 if(AOP_TYPE(right) != AOP_LIT
12344 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12345 && !IS_FUNC(OP_SYM_TYPE(right))
12346 && !IS_ITEMP(right))
12348 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12349 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12351 // set up table pointer
12352 if(is_LitOp(right)) {
12353 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12354 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12355 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12356 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12357 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12358 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12359 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12361 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12362 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12363 pic16_popCopyReg(&pic16_pc_tblptrl)));
12364 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12365 pic16_popCopyReg(&pic16_pc_tblptrh)));
12366 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12367 pic16_popCopyReg(&pic16_pc_tblptru)));
12370 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12371 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12373 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12374 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12375 pic16_popGet(AOP(result),offset)));
12379 /* FIXME: for pointers we need to extend differently (according
12380 * to pointer type DATA/CODE/EEPROM/... :*/
12381 size = getSize(OP_SYM_TYPE(right));
12382 if(AOP_SIZE(result) > size) {
12383 size = AOP_SIZE(result) - size;
12385 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12392 if (AOP_TYPE(right) == AOP_LIT && IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result)))
12394 /* Arrg -- a literal is cast into a generic pointer: how shall we decide which TAG
12395 * to assign (__data, __code, __eeprom, ???)??? */
12396 fprintf (stderr, "%s:%u(%s): creating generic pointer from literal defaults to __data TYPE*.\n\tPlease explicitly cast to (__data|__code) TYPE* in line %u if neccessary!\n",
12397 __FILE__, __LINE__, __FUNCTION__, ic->lineno);
12398 /* assume __data space */
12399 lit = (lit & 0x00ffff) | 0x800000;
12405 /* VR - What is this?! */
12406 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12407 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12408 if(aopIdx(AOP(result),0) == 4) {
12410 /* this is a workaround to save value of right into wreg too,
12411 * value of wreg is going to be used later */
12412 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12413 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12414 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12418 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12424 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12425 if(AOP_TYPE(right) == AOP_LIT) {
12427 if(know_W != (lit&0xff))
12428 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12430 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12432 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12436 } else if (AOP_TYPE(right) == AOP_CRY) {
12437 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12439 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12440 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12441 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12443 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12444 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12445 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12447 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12449 if(!_G.resDirect) /* use this aopForSym feature */
12450 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12457 pic16_freeAsmop (right,NULL,ic,FALSE);
12458 pic16_freeAsmop (result,NULL,ic,TRUE);
12461 /*-----------------------------------------------------------------*/
12462 /* genJumpTab - generates code for jump table */
12463 /*-----------------------------------------------------------------*/
12464 static void genJumpTab (iCode *ic)
12469 pCodeOp *jt_offs_hi;
12474 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12475 /* get the condition into accumulator */
12476 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12478 /* multiply by three */
12479 pic16_emitcode("add","a,acc");
12480 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12482 jtab = newiTempLabel(NULL);
12483 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12484 pic16_emitcode("jmp","@a+dptr");
12485 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12488 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12489 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12491 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12492 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12493 pic16_emitpLabel(jtab->key);
12497 jt_offs = pic16_popGetTempReg(0);
12498 jt_offs_hi = pic16_popGetTempReg(1);
12499 jt_label = pic16_popGetLabel (jtab->key);
12500 //fprintf (stderr, "Creating jump table...\n");
12502 // calculate offset into jump table (idx * sizeof (GOTO))
12503 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12504 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12505 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12506 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12507 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12508 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12509 pic16_emitpcode(POC_MOVWF , jt_offs);
12511 // prepare PCLATx (set to first entry in jump table)
12512 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12513 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12514 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12515 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12516 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12518 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12519 pic16_emitpcode(POC_ADDWF , jt_offs);
12520 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12521 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12523 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12525 // release temporaries and prepare jump into table (new PCL --> WREG)
12526 pic16_emitpcode(POC_MOVFW , jt_offs);
12527 pic16_popReleaseTempReg (jt_offs_hi, 1);
12528 pic16_popReleaseTempReg (jt_offs, 0);
12530 // jump into the table
12531 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12533 pic16_emitpLabelFORCE(jtab->key);
12536 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12537 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12539 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12540 /* now generate the jump labels */
12541 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12542 jtab = setNextItem(IC_JTLABELS(ic))) {
12543 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12544 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12547 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12551 /*-----------------------------------------------------------------*/
12552 /* genMixedOperation - gen code for operators between mixed types */
12553 /*-----------------------------------------------------------------*/
12555 TSD - Written for the PIC port - but this unfortunately is buggy.
12556 This routine is good in that it is able to efficiently promote
12557 types to different (larger) sizes. Unfortunately, the temporary
12558 variables that are optimized out by this routine are sometimes
12559 used in other places. So until I know how to really parse the
12560 iCode tree, I'm going to not be using this routine :(.
12562 static int genMixedOperation (iCode *ic)
12565 operand *result = IC_RESULT(ic);
12566 sym_link *ctype = operandType(IC_LEFT(ic));
12567 operand *right = IC_RIGHT(ic);
12573 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12575 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12581 nextright = IC_RIGHT(nextic);
12582 nextleft = IC_LEFT(nextic);
12583 nextresult = IC_RESULT(nextic);
12585 pic16_aopOp(right,ic,FALSE);
12586 pic16_aopOp(result,ic,FALSE);
12587 pic16_aopOp(nextright, nextic, FALSE);
12588 pic16_aopOp(nextleft, nextic, FALSE);
12589 pic16_aopOp(nextresult, nextic, FALSE);
12591 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12593 operand *t = right;
12597 pic16_emitcode(";remove right +","");
12599 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12601 operand *t = right;
12605 pic16_emitcode(";remove left +","");
12609 big = AOP_SIZE(nextleft);
12610 small = AOP_SIZE(nextright);
12612 switch(nextic->op) {
12615 pic16_emitcode(";optimize a +","");
12616 /* if unsigned or not an integral type */
12617 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12618 pic16_emitcode(";add a bit to something","");
12621 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12623 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12624 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12625 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12627 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12635 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12636 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12637 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12640 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12642 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12643 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12644 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12645 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12646 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12649 pic16_emitcode("rlf","known_zero,w");
12656 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12657 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12658 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12660 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12670 pic16_freeAsmop(right,NULL,ic,TRUE);
12671 pic16_freeAsmop(result,NULL,ic,TRUE);
12672 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12673 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12675 nextic->generated = 1;
12682 /*-----------------------------------------------------------------*/
12683 /* genCast - gen code for casting */
12684 /*-----------------------------------------------------------------*/
12685 static void genCast (iCode *ic)
12687 operand *result = IC_RESULT(ic);
12688 sym_link *ctype = operandType(IC_LEFT(ic));
12689 sym_link *rtype = operandType(IC_RIGHT(ic));
12690 sym_link *restype = operandType(IC_RESULT(ic));
12691 operand *right = IC_RIGHT(ic);
12697 /* if they are equivalent then do nothing */
12698 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12701 pic16_aopOp(result,ic,FALSE);
12702 pic16_aopOp(right,ic,FALSE) ;
12704 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12707 /* if the result is a bit */
12708 if (AOP_TYPE(result) == AOP_CRY) {
12710 /* if the right size is a literal then
12711 * we know what the value is */
12712 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12714 if (AOP_TYPE(right) == AOP_LIT) {
12715 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12716 pic16_popGet(AOP(result),0));
12718 if (((int) operandLitValue(right)))
12719 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12720 AOP(result)->aopu.aop_dir,
12721 AOP(result)->aopu.aop_dir);
12723 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12724 AOP(result)->aopu.aop_dir,
12725 AOP(result)->aopu.aop_dir);
12729 /* the right is also a bit variable */
12730 if (AOP_TYPE(right) == AOP_CRY) {
12732 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12734 pic16_emitcode("clrc","");
12735 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12736 AOP(right)->aopu.aop_dir,
12737 AOP(right)->aopu.aop_dir);
12738 pic16_aopPut(AOP(result),"c",0);
12742 /* we need to or */
12743 if (AOP_TYPE(right) == AOP_REG) {
12744 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12745 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12746 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12748 pic16_toBoolean(right);
12749 pic16_aopPut(AOP(result),"a",0);
12753 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12756 size = AOP_SIZE(result);
12758 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12760 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12761 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12762 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12765 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12770 if(IS_BITFIELD(getSpec(restype))
12771 && IS_BITFIELD(getSpec(rtype))) {
12772 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12775 /* port from pic14 to cope with generic pointers */
12776 if (IS_PTR(restype))
12778 operand *result = IC_RESULT(ic);
12779 //operand *left = IC_LEFT(ic);
12780 operand *right = IC_RIGHT(ic);
12783 /* copy common part */
12784 int max, size = AOP_SIZE(result);
12785 if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12786 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12788 /* warn if we discard generic opinter tag */
12789 if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
12791 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
12797 pic16_mov2w (AOP(right), size);
12798 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12800 pic16_addSign(result, max, 0);
12802 /* upcast into generic pointer type? */
12803 if (IS_GENPTR(restype) && !IS_GENPTR(rtype))
12805 //fprintf (stderr, "%s:%u: must determine pointer type (IS_PTR: %d, DCL_TYPE: %d)\n", __FUNCTION__, __LINE__, IS_PTR(rtype), IS_PTR(rtype) ? DCL_TYPE(rtype) : 0);
12808 switch (DCL_TYPE(rtype))
12810 case POINTER: /* __data */
12811 case FPOINTER: /* __data */
12812 assert (AOP_SIZE(right) == 2);
12816 case CPOINTER: /* __code */
12817 assert (AOP_SIZE(right) == 2);
12821 case GPOINTER: /* unknown destination, __data or __code */
12822 assert (AOP_SIZE(right) == 3);
12823 /* tag taken from right operand */
12827 assert (!"unhandled pointer type");
12830 /* convert other values into pointers to __data space */
12831 fprintf (stderr, "%s:%u(%s): creating generic pointer from non-pointer type -- assuming __data space\n", __FILE__, __LINE__, __FUNCTION__);
12835 assert (AOP_SIZE(result) == 3);
12837 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 2));
12839 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(tag));
12840 pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), 2));
12846 /* if they are the same size : or less */
12847 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12849 /* if they are in the same place */
12850 if (pic16_sameRegs(AOP(right),AOP(result)))
12853 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12855 if (IS_PTR_CONST(rtype))
12857 if (IS_CODEPTR(rtype))
12859 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12862 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12864 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12866 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12869 if(AOP_TYPE(right) == AOP_IMMD) {
12870 pCodeOp *pcop0, *pcop1, *pcop2;
12871 symbol *sym = OP_SYMBOL( right );
12873 size = AOP_SIZE(result);
12875 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12877 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12879 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12882 pic16_emitpcode(POC_MOVLW, pcop0);
12883 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12884 pic16_emitpcode(POC_MOVLW, pcop1);
12885 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12886 pic16_emitpcode(POC_MOVLW, pcop2);
12887 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12890 pic16_emitpcode(POC_MOVLW, pcop0);
12891 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12892 pic16_emitpcode(POC_MOVLW, pcop1);
12893 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12895 pic16_emitpcode(POC_MOVLW, pcop0);
12896 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12900 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12901 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12902 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12903 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12904 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12905 if(AOP_SIZE(result) <2)
12906 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12908 /* if they in different places then copy */
12909 size = AOP_SIZE(result);
12912 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12913 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12920 /* if the result is of type pointer */
12921 if (IS_PTR(ctype)) {
12923 sym_link *type = operandType(right);
12924 sym_link *etype = getSpec(type);
12926 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12928 /* pointer to generic pointer */
12929 if (IS_GENPTR(ctype)) {
12933 p_type = DCL_TYPE(type);
12935 /* we have to go by the storage class */
12936 p_type = PTR_TYPE(SPEC_OCLS(etype));
12938 /* if (SPEC_OCLS(etype)->codesp ) */
12939 /* p_type = CPOINTER ; */
12941 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12942 /* p_type = FPOINTER ; */
12944 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12945 /* p_type = PPOINTER; */
12947 /* if (SPEC_OCLS(etype) == idata ) */
12948 /* p_type = IPOINTER ; */
12950 /* p_type = POINTER ; */
12953 /* the first two bytes are known */
12954 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
12955 size = GPTRSIZE - 1;
12958 if(offset < AOP_SIZE(right)) {
12959 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12960 pic16_mov2f(AOP(result), AOP(right), offset);
12962 if ((AOP_TYPE(right) == AOP_PCODE) &&
12963 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12964 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12965 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12968 pic16_aopPut(AOP(result),
12969 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12974 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12977 /* the last byte depending on type */
12981 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12982 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12983 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12987 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12991 pic16_emitcode(";BUG!? ","%d",__LINE__);
12995 pic16_emitcode(";BUG!? ","%d",__LINE__);
13000 if (GPTRSIZE > AOP_SIZE(right)) {
13001 // assume data pointer... THIS MIGHT BE WRONG!
13002 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13003 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13005 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13010 /* this should never happen */
13011 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13012 "got unknown pointer type");
13015 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13021 /* just copy the pointers */
13022 size = AOP_SIZE(result);
13025 pic16_aopPut(AOP(result),
13026 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13035 /* so we now know that the size of destination is greater
13036 than the size of the source.
13037 Now, if the next iCode is an operator then we might be
13038 able to optimize the operation without performing a cast.
13040 if(genMixedOperation(ic))
13043 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13045 /* we move to result for the size of source */
13046 size = AOP_SIZE(right);
13051 pic16_mov2f(AOP(result), AOP(right), offset);
13055 /* now depending on the sign of the destination */
13056 size = AOP_SIZE(result) - AOP_SIZE(right);
13057 /* if unsigned or not an integral type */
13058 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13060 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13062 /* we need to extend the sign :( */
13065 /* Save one instruction of casting char to int */
13066 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13067 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13068 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13070 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13073 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13075 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13077 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13080 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13085 pic16_freeAsmop(right,NULL,ic,TRUE);
13086 pic16_freeAsmop(result,NULL,ic,TRUE);
13090 /*-----------------------------------------------------------------*/
13091 /* genDjnz - generate decrement & jump if not zero instrucion */
13092 /*-----------------------------------------------------------------*/
13093 static int genDjnz (iCode *ic, iCode *ifx)
13095 symbol *lbl, *lbl1;
13096 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13101 /* if the if condition has a false label
13102 then we cannot save */
13106 /* if the minus is not of the form
13108 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13109 !IS_OP_LITERAL(IC_RIGHT(ic)))
13112 if (operandLitValue(IC_RIGHT(ic)) != 1)
13115 /* if the size of this greater than one then no
13117 if (getSize(operandType(IC_RESULT(ic))) > 1)
13120 /* otherwise we can save BIG */
13121 lbl = newiTempLabel(NULL);
13122 lbl1= newiTempLabel(NULL);
13124 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13126 if (IS_AOP_PREG(IC_RESULT(ic))) {
13127 pic16_emitcode("dec","%s",
13128 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13129 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13130 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13134 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13135 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13137 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13138 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13142 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13143 ifx->generated = 1;
13147 /*-----------------------------------------------------------------*/
13148 /* genReceive - generate code for a receive iCode */
13149 /*-----------------------------------------------------------------*/
13150 static void genReceive (iCode *ic)
13156 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13157 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13159 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13161 if (isOperandInFarSpace(IC_RESULT(ic))
13162 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13163 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13165 int size = getSize(operandType(IC_RESULT(ic)));
13166 int offset = pic16_fReturnSizePic - size;
13170 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13171 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13175 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13177 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13178 size = AOP_SIZE(IC_RESULT(ic));
13181 pic16_emitcode ("pop","acc");
13182 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13185 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13187 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13190 /* set pseudo stack pointer to where it should be - dw*/
13191 GpsuedoStkPtr = ic->parmBytes;
13193 /* setting GpsuedoStkPtr has side effects here: */
13194 assignResultValue(IC_RESULT(ic), 0);
13197 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13200 /*-----------------------------------------------------------------*/
13201 /* genDummyRead - generate code for dummy read of volatiles */
13202 /*-----------------------------------------------------------------*/
13204 genDummyRead (iCode * ic)
13210 if (op && IS_SYMOP(op)) {
13211 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13212 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13215 pic16_aopOp (op, ic, FALSE);
13216 for (i=0; i < AOP_SIZE(op); i++) {
13217 // may need to protect this from the peepholer -- this is not nice but works...
13218 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13219 pic16_mov2w (AOP(op),i);
13220 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13222 pic16_freeAsmop (op, NULL, ic, TRUE);
13224 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13228 /*-----------------------------------------------------------------*/
13229 /* genpic16Code - generate code for pic16 based controllers */
13230 /*-----------------------------------------------------------------*/
13232 * At this point, ralloc.c has gone through the iCode and attempted
13233 * to optimize in a way suitable for a PIC. Now we've got to generate
13234 * PIC instructions that correspond to the iCode.
13236 * Once the instructions are generated, we'll pass through both the
13237 * peep hole optimizer and the pCode optimizer.
13238 *-----------------------------------------------------------------*/
13240 void genpic16Code (iCode *lic)
13245 lineHead = lineCurr = NULL;
13247 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13248 pic16_addpBlock(pb);
13251 /* if debug information required */
13252 if (options.debug && currFunc) {
13254 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13259 for (ic = lic ; ic ; ic = ic->next ) {
13261 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13262 if ( cln != ic->lineno ) {
13263 if ( options.debug ) {
13264 debugFile->writeCLine (ic);
13267 if(!options.noCcodeInAsm) {
13268 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13269 printCLine(ic->filename, ic->lineno)));
13275 if(options.iCodeInAsm) {
13278 /* insert here code to print iCode as comment */
13279 l = Safe_strdup(printILine(ic));
13280 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13283 /* if the result is marked as
13284 * spilt and rematerializable or code for
13285 * this has already been generated then
13287 if (resultRemat(ic) || ic->generated )
13290 /* depending on the operation */
13309 /* IPOP happens only when trying to restore a
13310 * spilt live range, if there is an ifx statement
13311 * following this pop then the if statement might
13312 * be using some of the registers being popped which
13313 * would destroy the contents of the register so
13314 * we need to check for this condition and handle it */
13316 && ic->next->op == IFX
13317 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13318 genIfx (ic->next,ic);
13336 genEndFunction (ic);
13352 pic16_genPlus (ic) ;
13356 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13357 pic16_genMinus (ic);
13373 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13377 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13383 /* note these two are xlated by algebraic equivalence
13384 * during parsing SDCC.y */
13385 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13386 "got '>=' or '<=' shouldn't have come here");
13390 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13402 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13406 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13410 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13434 genRightShift (ic);
13437 case GET_VALUE_AT_ADDRESS:
13442 if (POINTER_SET(ic))
13469 addSet(&_G.sendSet,ic);
13472 case DUMMY_READ_VOLATILE:
13482 /* now we are ready to call the
13483 peep hole optimizer */
13484 if (!options.nopeep)
13485 peepHole (&lineHead);
13487 /* now do the actual printing */
13488 printLine (lineHead, codeOutFile);
13491 DFPRINTF((stderr,"printing pBlock\n\n"));
13492 pic16_printpBlock(stdout,pb);