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++));
2682 #if !defined(GEN_Not)
2683 /*-----------------------------------------------------------------*/
2684 /* genNot - generate code for ! operation */
2685 /*-----------------------------------------------------------------*/
2686 static void pic16_genNot (iCode *ic)
2692 /* assign asmOps to operand & result */
2693 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2694 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2696 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2697 /* if in bit space then a special case */
2698 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2699 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2700 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2701 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2703 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2704 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2705 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2710 size = AOP_SIZE(IC_LEFT(ic));
2712 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2713 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2714 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2717 pic16_toBoolean(IC_LEFT(ic));
2719 tlbl = newiTempLabel(NULL);
2720 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2721 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2722 pic16_outBitC(IC_RESULT(ic));
2725 /* release the aops */
2726 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2727 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2732 #if !defined(GEN_Cpl)
2733 /*-----------------------------------------------------------------*/
2734 /* genCpl - generate code for complement */
2735 /*-----------------------------------------------------------------*/
2736 static void pic16_genCpl (iCode *ic)
2742 /* assign asmOps to operand & result */
2743 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2744 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2746 /* if both are in bit space then
2748 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2749 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2751 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2752 pic16_emitcode("cpl","c");
2753 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2757 size = AOP_SIZE(IC_RESULT(ic));
2760 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2762 pic16_emitcode("cpl","a");
2763 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2765 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2766 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2768 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2769 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2777 /* release the aops */
2778 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2779 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2783 /*-----------------------------------------------------------------*/
2784 /* genUminusFloat - unary minus for floating points */
2785 /*-----------------------------------------------------------------*/
2786 static void genUminusFloat(operand *op,operand *result)
2788 int size ,offset =0 ;
2791 /* for this we just need to flip the
2792 first it then copy the rest in place */
2793 size = AOP_SIZE(op);
2796 pic16_mov2f(AOP(result), AOP(op), offset);
2800 /* toggle the MSB's highest bit */
2801 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2804 /*-----------------------------------------------------------------*/
2805 /* genUminus - unary minus code generation */
2806 /*-----------------------------------------------------------------*/
2807 static void genUminus (iCode *ic)
2810 sym_link *optype, *rtype;
2817 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2818 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2820 /* if both in bit space then special case */
2821 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2822 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2824 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2825 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2826 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2830 optype = operandType(IC_LEFT(ic));
2831 rtype = operandType(IC_RESULT(ic));
2834 /* if float then do float stuff */
2835 if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2836 if(IS_FIXED(optype))
2837 debugf("implement fixed16x16 type\n", 0);
2839 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2843 /* otherwise subtract from zero by taking the 2's complement */
2844 size = AOP_SIZE(IC_LEFT(ic));
2845 label = newiTempLabel ( NULL );
2847 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2848 for (i=size-1; i > 0; i--) {
2849 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2851 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2852 for (i=1; i < size; i++) {
2853 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2854 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2857 for (i=size-1; i >= 0; i--) {
2858 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2859 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2862 for (i=0; i < size-2; i++) {
2863 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2864 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2866 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2868 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2871 pic16_emitpLabel (label->key);
2874 /* release the aops */
2875 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2876 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2880 /*-----------------------------------------------------------------*/
2881 /* saveRegisters - will look for a call and save the registers */
2882 /*-----------------------------------------------------------------*/
2883 static void saveRegisters(iCode *lic)
2890 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2892 for (ic = lic ; ic ; ic = ic->next)
2893 if (ic->op == CALL || ic->op == PCALL)
2897 fprintf(stderr,"found parameter push with no function call\n");
2901 /* if the registers have been saved already then
2903 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2906 /* find the registers in use at this time
2907 and push them away to safety */
2908 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2912 if (options.useXstack) {
2913 if (bitVectBitValue(rsave,R0_IDX))
2914 pic16_emitcode("mov","b,r0");
2915 pic16_emitcode("mov","r0,%s",spname);
2916 for (i = 0 ; i < pic16_nRegs ; i++) {
2917 if (bitVectBitValue(rsave,i)) {
2919 pic16_emitcode("mov","a,b");
2921 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2922 pic16_emitcode("movx","@r0,a");
2923 pic16_emitcode("inc","r0");
2926 pic16_emitcode("mov","%s,r0",spname);
2927 if (bitVectBitValue(rsave,R0_IDX))
2928 pic16_emitcode("mov","r0,b");
2930 //for (i = 0 ; i < pic16_nRegs ; i++) {
2931 // if (bitVectBitValue(rsave,i))
2932 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2935 dtype = operandType(IC_LEFT(ic));
2936 if (currFunc && dtype &&
2937 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2938 IFFUNC_ISISR(currFunc->type) &&
2941 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2944 /*-----------------------------------------------------------------*/
2945 /* unsaveRegisters - pop the pushed registers */
2946 /*-----------------------------------------------------------------*/
2947 static void unsaveRegisters (iCode *ic)
2952 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2953 /* find the registers in use at this time
2954 and push them away to safety */
2955 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2958 if (options.useXstack) {
2959 pic16_emitcode("mov","r0,%s",spname);
2960 for (i = pic16_nRegs ; i >= 0 ; i--) {
2961 if (bitVectBitValue(rsave,i)) {
2962 pic16_emitcode("dec","r0");
2963 pic16_emitcode("movx","a,@r0");
2965 pic16_emitcode("mov","b,a");
2967 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2971 pic16_emitcode("mov","%s,r0",spname);
2972 if (bitVectBitValue(rsave,R0_IDX))
2973 pic16_emitcode("mov","r0,b");
2975 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2976 // if (bitVectBitValue(rsave,i))
2977 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2984 /*-----------------------------------------------------------------*/
2986 /*-----------------------------------------------------------------*/
2987 static void pushSide(operand * oper, int size)
2990 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2992 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2993 if (AOP_TYPE(oper) != AOP_REG &&
2994 AOP_TYPE(oper) != AOP_DIR &&
2996 pic16_emitcode("mov","a,%s",l);
2997 pic16_emitcode("push","acc");
2999 pic16_emitcode("push","%s",l);
3004 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
3006 if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
3007 pic16_emitpcode(POC_MOVFW, src);
3008 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
3010 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3011 src, pic16_popGet(AOP(op), offset)));
3016 /*-----------------------------------------------------------------*/
3017 /* assignResultValue - assign results to oper, rescall==1 is */
3018 /* called from genCall() or genPcall() */
3019 /*-----------------------------------------------------------------*/
3020 static void assignResultValue(operand * oper, int rescall)
3022 int size = AOP_SIZE(oper);
3026 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3027 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3030 /* assign result from a call/pcall function() */
3032 /* function results are stored in a special order,
3033 * see top of file with Function return policy, or manual */
3036 /* 8-bits, result in WREG */
3037 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3040 /* 16-bits, result in PRODL:WREG */
3041 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3045 /* 24-bits, result in PRODH:PRODL:WREG */
3046 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3050 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3051 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3055 /* >32-bits, result on stack, and FSR0 points to beginning.
3056 * Fix stack when done */
3058 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3060 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3061 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3063 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3068 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3069 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3070 if(STACK_MODEL_LARGE) {
3072 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3076 int areg = 0; /* matching argument register */
3078 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3079 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3082 /* its called from genReceive (probably) -- VR */
3083 /* I hope this code will not be called from somewhere else in the future!
3084 * We manually set the pseudo stack pointer in genReceive. - dw
3086 if(!GpsuedoStkPtr && _G.useWreg) {
3087 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3089 /* The last byte in the assignment is in W */
3090 if(areg <= GpsuedoStkPtr) {
3092 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3094 // debugf("receive from WREG\n", 0);
3096 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3099 _G.stack_lat = AOP_SIZE(oper)-1;
3104 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3105 // debugf("receive from STACK\n", 0);
3112 /*-----------------------------------------------------------------*/
3113 /* genIpush - generate code for pushing this gets a little complex */
3114 /*-----------------------------------------------------------------*/
3115 static void genIpush (iCode *ic)
3117 // int size, offset=0;
3120 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3123 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3125 /* send to stack as normal */
3126 addSet(&_G.sendSet,ic);
3127 // addSetHead(&_G.sendSet,ic);
3128 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3133 int size, offset = 0 ;
3137 /* if this is not a parm push : ie. it is spill push
3138 and spill push is always done on the local stack */
3139 if (!ic->parmPush) {
3141 /* and the item is spilt then do nothing */
3142 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3145 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3146 size = AOP_SIZE(IC_LEFT(ic));
3147 /* push it on the stack */
3149 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3154 pic16_emitcode("push","%s",l);
3159 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3163 /*-----------------------------------------------------------------*/
3164 /* genIpop - recover the registers: can happen only for spilling */
3165 /*-----------------------------------------------------------------*/
3166 static void genIpop (iCode *ic)
3169 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3174 /* if the temp was not pushed then */
3175 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3178 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3179 size = AOP_SIZE(IC_LEFT(ic));
3182 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3185 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3190 /*-----------------------------------------------------------------*/
3191 /* unsaverbank - restores the resgister bank from stack */
3192 /*-----------------------------------------------------------------*/
3193 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3195 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3201 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3203 if (options.useXstack) {
3205 r = getFreePtr(ic,&aop,FALSE);
3208 pic16_emitcode("mov","%s,_spx",r->name);
3209 pic16_emitcode("movx","a,@%s",r->name);
3210 pic16_emitcode("mov","psw,a");
3211 pic16_emitcode("dec","%s",r->name);
3214 pic16_emitcode ("pop","psw");
3217 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3218 if (options.useXstack) {
3219 pic16_emitcode("movx","a,@%s",r->name);
3220 //pic16_emitcode("mov","(%s+%d),a",
3221 // regspic16[i].base,8*bank+regspic16[i].offset);
3222 pic16_emitcode("dec","%s",r->name);
3225 pic16_emitcode("pop",""); //"(%s+%d)",
3226 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3229 if (options.useXstack) {
3231 pic16_emitcode("mov","_spx,%s",r->name);
3232 pic16_freeAsmop(NULL,aop,ic,TRUE);
3238 /*-----------------------------------------------------------------*/
3239 /* saverbank - saves an entire register bank on the stack */
3240 /*-----------------------------------------------------------------*/
3241 static void saverbank (int bank, iCode *ic, bool pushPsw)
3243 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3249 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3250 if (options.useXstack) {
3253 r = getFreePtr(ic,&aop,FALSE);
3254 pic16_emitcode("mov","%s,_spx",r->name);
3258 for (i = 0 ; i < pic16_nRegs ;i++) {
3259 if (options.useXstack) {
3260 pic16_emitcode("inc","%s",r->name);
3261 //pic16_emitcode("mov","a,(%s+%d)",
3262 // regspic16[i].base,8*bank+regspic16[i].offset);
3263 pic16_emitcode("movx","@%s,a",r->name);
3265 pic16_emitcode("push","");// "(%s+%d)",
3266 //regspic16[i].base,8*bank+regspic16[i].offset);
3270 if (options.useXstack) {
3271 pic16_emitcode("mov","a,psw");
3272 pic16_emitcode("movx","@%s,a",r->name);
3273 pic16_emitcode("inc","%s",r->name);
3274 pic16_emitcode("mov","_spx,%s",r->name);
3275 pic16_freeAsmop (NULL,aop,ic,TRUE);
3278 pic16_emitcode("push","psw");
3280 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3288 static int wparamCmp(void *p1, void *p2)
3290 return (!strcmp((char *)p1, (char *)p2));
3293 int inWparamList(char *s)
3295 return isinSetWith(wparamList, s, wparamCmp);
3299 /*-----------------------------------------------------------------*/
3300 /* genCall - generates a call statement */
3301 /*-----------------------------------------------------------------*/
3302 static void genCall (iCode *ic)
3312 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3313 /* if caller saves & we have not saved then */
3314 // if (!ic->regsSaved)
3315 // saveRegisters(ic);
3317 /* initialise stackParms for IPUSH pushes */
3318 // stackParms = psuedoStkPtr;
3319 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3320 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3321 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3324 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3327 /* if send set is not empty the assign */
3330 int psuedoStkPtr=-1;
3331 int firstTimeThruLoop = 1;
3334 /* reverse sendSet if function is not reentrant */
3335 if(!IFFUNC_ISREENT(ftype))
3336 _G.sendSet = reverseSet(_G.sendSet);
3338 /* First figure how many parameters are getting passed */
3342 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3346 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3347 size = AOP_SIZE(IC_LEFT(sic));
3351 /* pass the last byte through WREG */
3355 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3356 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3357 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3359 if(!firstTimeThruLoop) {
3360 /* If this is not the first time we've been through the loop
3361 * then we need to save the parameter in a temporary
3362 * register. The last byte of the last parameter is
3366 // --psuedoStkPtr; // sanity check
3370 firstTimeThruLoop=0;
3372 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3377 /* all arguments are passed via stack */
3381 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3382 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3383 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3385 // pushaop(AOP(IC_LEFT(sic)), size);
3386 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3393 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3397 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3398 pushw(); /* save last parameter to stack if functions has varargs */
3402 } else use_wreg = 0;
3404 _G.stackRegSet = _G.sendSet;
3409 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3413 /* if we need to assign a result value */
3414 if ((IS_ITEMP(IC_RESULT(ic))
3415 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3416 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3417 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3420 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3423 assignResultValue(IC_RESULT(ic), 1);
3425 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3426 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3428 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3431 if(!stackParms && ic->parmBytes) {
3432 stackParms = ic->parmBytes;
3435 stackParms -= use_wreg;
3438 if(stackParms == 1) {
3439 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3441 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3442 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3444 if(STACK_MODEL_LARGE) {
3446 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3451 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3454 /* adjust the stack for parameters if required */
3455 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3458 /* if register bank was saved then pop them */
3460 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3462 /* if we hade saved some registers then unsave them */
3463 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3464 unsaveRegisters (ic);
3470 /*-----------------------------------------------------------------*/
3471 /* genPcall - generates a call by pointer statement */
3472 /* new version, created from genCall - HJD */
3473 /*-----------------------------------------------------------------*/
3474 static void genPcall (iCode *ic)
3476 sym_link *ftype, *fntype;
3478 symbol *retlbl = newiTempLabel(NULL);
3479 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3483 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3484 fntype = operandType( IC_LEFT(ic) )->next;
3486 /* if send set is not empty the assign */
3489 int psuedoStkPtr=-1;
3491 /* reverse sendSet if function is not reentrant */
3492 if(!IFFUNC_ISREENT(fntype))
3493 _G.sendSet = reverseSet(_G.sendSet);
3497 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3500 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3501 size = AOP_SIZE(IC_LEFT(sic));
3504 /* all parameters are passed via stack, since WREG is clobbered
3505 * by the calling sequence */
3507 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3508 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3509 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3511 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3515 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3518 _G.stackRegSet = _G.sendSet;
3522 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3524 // push return address
3525 // push $ on return stack, then replace with retlbl
3527 /* Thanks to Thorsten Klose for pointing out that the following
3528 * snippet should be interrupt safe */
3529 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3530 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3532 pic16_emitpcodeNULLop(POC_PUSH);
3534 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3535 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3536 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3537 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3538 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3539 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3542 /* restore interrupt control register */
3543 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3544 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3546 /* make the call by writing the pointer into pc */
3547 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3548 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3550 // note: MOVFF to PCL not allowed
3551 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3552 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3555 /* return address is here: (X) */
3556 pic16_emitpLabelFORCE(retlbl->key);
3558 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3561 /* if we need assign a result value */
3562 if ((IS_ITEMP(IC_RESULT(ic))
3563 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3564 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3565 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3568 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3571 assignResultValue(IC_RESULT(ic), 1);
3573 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3574 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3576 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3579 // stackParms -= use_wreg;
3582 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3583 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3584 if(STACK_MODEL_LARGE) {
3586 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3591 /*-----------------------------------------------------------------*/
3592 /* resultRemat - result is rematerializable */
3593 /*-----------------------------------------------------------------*/
3594 static int resultRemat (iCode *ic)
3596 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3597 if (SKIP_IC(ic) || ic->op == IFX)
3600 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3601 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3602 if (sym->remat && !POINTER_SET(ic))
3609 #if defined(__BORLANDC__) || defined(_MSC_VER)
3610 #define STRCASECMP stricmp
3612 #define STRCASECMP strcasecmp
3616 /*-----------------------------------------------------------------*/
3617 /* inExcludeList - return 1 if the string is in exclude Reg list */
3618 /*-----------------------------------------------------------------*/
3619 static bool inExcludeList(char *s)
3621 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3624 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3625 if (options.excludeRegs[i] &&
3626 STRCASECMP(options.excludeRegs[i],"none") == 0)
3629 for ( i = 0 ; options.excludeRegs[i]; i++) {
3630 if (options.excludeRegs[i] &&
3631 STRCASECMP(s,options.excludeRegs[i]) == 0)
3638 /*-----------------------------------------------------------------*/
3639 /* genFunction - generated code for function entry */
3640 /*-----------------------------------------------------------------*/
3641 static void genFunction (iCode *ic)
3647 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3649 pic16_labelOffset += (max_key+4);
3654 ftype = operandType(IC_LEFT(ic));
3655 sym = OP_SYMBOL(IC_LEFT(ic));
3657 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3658 /* create an absolute section at the interrupt vector:
3659 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3664 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3666 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3667 sprintf(asymname, "ivec_%s", sym->name);
3669 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3671 /* when an interrupt is declared as naked, do not emit the special
3672 * wrapper segment at vector address. The user should take care for
3673 * this instead. -- VR */
3675 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3676 asym = newSymbol(asymname, 0);
3677 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3678 pic16_addpBlock( apb );
3680 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3681 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3682 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3683 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3684 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3686 /* mark the end of this tiny function */
3687 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3689 sprintf(asymname, "%s", sym->rname);
3695 abSym = Safe_calloc(1, sizeof(absSym));
3696 strcpy(abSym->name, asymname);
3698 switch( FUNC_INTNO(sym->type) ) {
3699 case 0: abSym->address = 0x000000; break;
3700 case 1: abSym->address = 0x000008; break;
3701 case 2: abSym->address = 0x000018; break;
3704 // fprintf(stderr, "no interrupt number is given\n");
3705 abSym->address = -1; break;
3708 /* relocate interrupt vectors if needed */
3709 if(abSym->address != -1)
3710 abSym->address += pic16_options.ivt_loc;
3712 addSet(&absSymSet, abSym);
3716 /* create the function header */
3717 pic16_emitcode(";","-----------------------------------------");
3718 pic16_emitcode(";"," function %s",sym->name);
3719 pic16_emitcode(";","-----------------------------------------");
3721 pic16_emitcode("","%s:",sym->rname);
3722 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3727 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3728 if(!strcmp(ab->name, sym->rname)) {
3729 pic16_pBlockConvert2Absolute(pb);
3735 if(IFFUNC_ISNAKED(ftype)) {
3736 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3740 /* if critical function then turn interrupts off */
3741 if (IFFUNC_ISCRITICAL(ftype)) {
3742 //pic16_emitcode("clr","ea");
3745 currFunc = sym; /* update the currFunc symbol */
3746 _G.fregsUsed = sym->regsUsed;
3747 _G.sregsAlloc = newBitVect(128);
3750 /* if this is an interrupt service routine then
3751 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3752 if (IFFUNC_ISISR(sym->type)) {
3753 _G.usefastretfie = 1; /* use shadow registers by default */
3755 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3756 if(!FUNC_ISSHADOWREGS(sym->type)) {
3757 /* do not save WREG,STATUS,BSR for high priority interrupts
3758 * because they are stored in the hardware shadow registers already */
3759 _G.usefastretfie = 0;
3760 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3761 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3762 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3765 /* these should really be optimized somehow, because not all
3766 * interrupt handlers modify them */
3767 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3768 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3769 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3770 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3772 // pic16_pBlockConvert2ISR(pb);
3775 /* emit code to setup stack frame if user enabled,
3776 * and function is not main() */
3778 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3779 if(strcmp(sym->name, "main")) {
3781 || !options.ommitFramePtr
3783 || IFFUNC_ARGS(sym->type)
3784 || FUNC_HASSTACKPARM(sym->etype)
3786 /* setup the stack frame */
3787 if(STACK_MODEL_LARGE)
3788 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3789 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3791 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3792 if(STACK_MODEL_LARGE)
3793 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3797 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3800 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3802 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3803 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3805 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3808 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3809 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3816 /* if callee-save to be used for this function
3817 * then save the registers being used in this function */
3818 // if (IFFUNC_CALLEESAVES(sym->type))
3822 /* if any registers used */
3823 if (sym->regsUsed) {
3824 /* save the registers used */
3825 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3826 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3827 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3828 if (bitVectBitValue(sym->regsUsed,i)) {
3829 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3832 if(!pic16_regWithIdx(i)->wasUsed) {
3833 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3834 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3835 pic16_regWithIdx(i)->wasUsed = 1;
3839 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3843 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3844 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3847 /*-----------------------------------------------------------------*/
3848 /* genEndFunction - generates epilogue for functions */
3849 /*-----------------------------------------------------------------*/
3850 static void genEndFunction (iCode *ic)
3852 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3856 if(IFFUNC_ISNAKED(sym->type)) {
3857 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3863 /* add code for ISCRITICAL */
3864 if(IFFUNC_ISCRITICAL(sym->type)) {
3865 /* if critical function, turn on interrupts */
3867 /* TODO: add code here -- VR */
3870 // sym->regsUsed = _G.fregsUsed;
3872 /* now we need to restore the registers */
3873 /* if any registers used */
3875 /* first restore registers that might be used for stack access */
3876 if(_G.sregsAllocSet) {
3879 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3880 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3881 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3885 if (sym->regsUsed) {
3888 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3889 /* restore registers used */
3890 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3891 for ( i = sym->regsUsed->size; i >= 0; i--) {
3892 if (bitVectBitValue(sym->regsUsed,i)) {
3893 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3897 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3902 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3904 if (sym->stack == 1) {
3905 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3906 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3908 // we have to add more than one...
3909 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3910 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3911 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3913 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3914 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3915 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3919 if(strcmp(sym->name, "main")) {
3921 || !options.ommitFramePtr
3923 || IFFUNC_ARGS(sym->type)
3924 || FUNC_HASSTACKPARM(sym->etype)
3926 /* restore stack frame */
3927 if(STACK_MODEL_LARGE)
3928 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3929 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3935 if (IFFUNC_ISISR(sym->type)) {
3936 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3937 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3938 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3939 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3941 if(!FUNC_ISSHADOWREGS(sym->type)) {
3942 /* do not restore interrupt vector for WREG,STATUS,BSR
3943 * for high priority interrupt, see genFunction */
3944 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3945 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3946 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3948 // _G.interruptvector = 0; /* sanity check */
3951 /* if debug then send end of function */
3952 /* if (options.debug && currFunc) */
3954 debugFile->writeEndFunction (currFunc, ic, 1);
3957 if(_G.usefastretfie)
3958 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3960 pic16_emitpcodeNULLop(POC_RETFIE);
3962 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3964 _G.usefastretfie = 0;
3968 if (IFFUNC_ISCRITICAL(sym->type)) {
3969 pic16_emitcode("setb","ea");
3972 /* if debug then send end of function */
3974 debugFile->writeEndFunction (currFunc, ic, 1);
3977 /* insert code to restore stack frame, if user enabled it
3978 * and function is not main() */
3981 pic16_emitpcodeNULLop(POC_RETURN);
3983 /* Mark the end of a function */
3984 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3988 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3990 unsigned long lit=1;
3995 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3996 if(AOP_TYPE(op) == AOP_LIT) {
3997 if(!IS_FLOAT(operandType( op ))) {
3998 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
4001 unsigned long lit_int;
4005 /* take care if literal is a float */
4006 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4012 if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
4013 pic16_emitpcode(POC_CLRF, dest);
4015 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
4016 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
4019 if(dest->type == PO_WREG && (offset == 0)) {
4020 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4023 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4027 /*-----------------------------------------------------------------*/
4028 /* genRet - generate code for return statement */
4029 /*-----------------------------------------------------------------*/
4030 static void genRet (iCode *ic)
4036 /* if we have no return value then
4037 * just generate the "ret" */
4042 /* we have something to return then
4043 * move the return value into place */
4044 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4045 size = AOP_SIZE(IC_LEFT(ic));
4049 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4052 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4055 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4057 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4060 /* >32-bits, setup stack and FSR0 */
4062 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4063 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4065 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4067 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4072 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4073 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4075 if(STACK_MODEL_LARGE) {
4076 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4077 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4079 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4084 /* old code, left here for reference -- VR */
4088 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4090 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4091 pic16_emitpcomment("push %s",l);
4094 DEBUGpic16_emitcode(";", "%d", __LINE__);
4095 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4096 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4098 if (strcmp(fReturn[offset],l)) {
4099 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4100 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4101 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4103 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4107 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4117 if (strcmp(fReturn[pushed],"a"))
4118 pic16_emitcode("pop",fReturn[pushed]);
4120 pic16_emitcode("pop","acc");
4126 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4129 /* generate a jump to the return label
4130 * if the next is not the return statement */
4131 if (!(ic->next && ic->next->op == LABEL
4132 && IC_LABEL(ic->next) == returnLabel)) {
4134 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4135 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4139 /*-----------------------------------------------------------------*/
4140 /* genLabel - generates a label */
4141 /*-----------------------------------------------------------------*/
4142 static void genLabel (iCode *ic)
4146 /* special case never generate */
4147 if (IC_LABEL(ic) == entryLabel)
4150 pic16_emitpLabel(IC_LABEL(ic)->key);
4151 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4154 /*-----------------------------------------------------------------*/
4155 /* genGoto - generates a goto */
4156 /*-----------------------------------------------------------------*/
4158 static void genGoto (iCode *ic)
4161 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4162 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4166 /*-----------------------------------------------------------------*/
4167 /* genMultbits :- multiplication of bits */
4168 /*-----------------------------------------------------------------*/
4169 static void genMultbits (operand *left,
4175 if(!pic16_sameRegs(AOP(result),AOP(right)))
4176 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4178 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4179 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4180 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4185 /*-----------------------------------------------------------------*/
4186 /* genMultOneByte : 8 bit multiplication & division */
4187 /*-----------------------------------------------------------------*/
4188 static void genMultOneByte (operand *left,
4194 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4195 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4197 /* (if two literals, the value is computed before) */
4198 /* if one literal, literal on the right */
4199 if (AOP_TYPE(left) == AOP_LIT){
4205 /* size is already checked in genMult == 1 */
4206 // size = AOP_SIZE(result);
4208 if (AOP_TYPE(right) == AOP_LIT){
4209 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4210 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4211 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4212 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4214 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4215 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4216 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4217 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4220 pic16_genMult8X8_8 (left, right,result);
4223 /*-----------------------------------------------------------------*/
4224 /* genMultOneWord : 16 bit multiplication */
4225 /*-----------------------------------------------------------------*/
4226 static void genMultOneWord (operand *left,
4231 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4232 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4234 /* (if two literals, the value is computed before)
4235 * if one literal, literal on the right */
4236 if (AOP_TYPE(left) == AOP_LIT){
4242 /* size is checked already == 2 */
4243 // size = AOP_SIZE(result);
4245 if (AOP_TYPE(right) == AOP_LIT) {
4246 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4247 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4248 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4249 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4251 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4252 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4253 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4254 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4257 pic16_genMult16X16_16(left, right,result);
4260 /*-----------------------------------------------------------------*/
4261 /* genMultOneLong : 32 bit multiplication */
4262 /*-----------------------------------------------------------------*/
4263 static void genMultOneLong (operand *left,
4268 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4269 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4271 /* (if two literals, the value is computed before)
4272 * if one literal, literal on the right */
4273 if (AOP_TYPE(left) == AOP_LIT){
4279 /* size is checked already == 4 */
4280 // size = AOP_SIZE(result);
4282 if (AOP_TYPE(right) == AOP_LIT) {
4283 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4284 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4285 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4286 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4288 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4289 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4290 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4291 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4294 pic16_genMult32X32_32(left, right,result);
4299 /*-----------------------------------------------------------------*/
4300 /* genMult - generates code for multiplication */
4301 /*-----------------------------------------------------------------*/
4302 static void genMult (iCode *ic)
4304 operand *left = IC_LEFT(ic);
4305 operand *right = IC_RIGHT(ic);
4306 operand *result= IC_RESULT(ic);
4309 /* assign the amsops */
4310 pic16_aopOp (left,ic,FALSE);
4311 pic16_aopOp (right,ic,FALSE);
4312 pic16_aopOp (result,ic,TRUE);
4314 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4316 /* special cases first *
4318 if (AOP_TYPE(left) == AOP_CRY
4319 && AOP_TYPE(right)== AOP_CRY) {
4320 genMultbits(left,right,result);
4324 /* if both are of size == 1 */
4325 if(AOP_SIZE(left) == 1
4326 && AOP_SIZE(right) == 1) {
4327 genMultOneByte(left,right,result);
4331 /* if both are of size == 2 */
4332 if(AOP_SIZE(left) == 2
4333 && AOP_SIZE(right) == 2) {
4334 genMultOneWord(left, right, result);
4338 /* if both are of size == 4 */
4339 if(AOP_SIZE(left) == 4
4340 && AOP_SIZE(right) == 4) {
4341 genMultOneLong(left, right, result);
4345 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4348 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4349 /* should have been converted to function call */
4353 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4354 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4355 pic16_freeAsmop(result,NULL,ic,TRUE);
4358 /*-----------------------------------------------------------------*/
4359 /* genDivbits :- division of bits */
4360 /*-----------------------------------------------------------------*/
4361 static void genDivbits (operand *left,
4368 /* the result must be bit */
4369 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4370 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4374 pic16_emitcode("div","ab");
4375 pic16_emitcode("rrc","a");
4376 pic16_aopPut(AOP(result),"c",0);
4379 /*-----------------------------------------------------------------*/
4380 /* genDivOneByte : 8 bit division */
4381 /*-----------------------------------------------------------------*/
4382 static void genDivOneByte (operand *left,
4386 sym_link *opetype = operandType(result);
4391 /* result = divident / divisor
4392 * - divident may be a register or a literal,
4393 * - divisor may be a register or a literal,
4394 * so there are 3 cases (literal / literal is optimized
4395 * by the front-end) to handle.
4396 * In addition we must handle signed and unsigned, which
4397 * result in 6 final different cases -- VR */
4401 size = AOP_SIZE(result) - 1;
4403 /* signed or unsigned */
4404 if (SPEC_USIGN(opetype)) {
4405 pCodeOp *pct1, /* count */
4408 symbol *label1, *label2, *label3;;
4411 /* unsigned is easy */
4413 pct1 = pic16_popGetTempReg(1);
4414 pct2 = pic16_popGetTempReg(1);
4415 pct3 = pic16_popGetTempReg(1);
4417 label1 = newiTempLabel(NULL);
4418 label2 = newiTempLabel(NULL);
4419 label3 = newiTempLabel(NULL);
4421 /* the following algorithm is extracted from divuint.c */
4423 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4424 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4426 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4428 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4430 pic16_emitpLabel(label1->key);
4433 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4437 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4441 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4443 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4444 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4446 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4447 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4448 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4450 pic16_emitpLabel( label3->key );
4451 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4452 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4456 pic16_emitpLabel(label2->key);
4457 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4458 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4459 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4461 /* result is in wreg */
4462 if(AOP_TYPE(result) != AOP_ACC)
4463 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4465 pic16_popReleaseTempReg( pct3, 1);
4466 pic16_popReleaseTempReg( pct2, 1);
4467 pic16_popReleaseTempReg( pct1, 1);
4472 /* signed is a little bit more difficult */
4474 /* save the signs of the operands */
4475 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4477 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4478 pic16_emitcode("push","acc"); /* save it on the stack */
4480 /* now sign adjust for both left & right */
4481 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4483 lbl = newiTempLabel(NULL);
4484 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4485 pic16_emitcode("cpl","a");
4486 pic16_emitcode("inc","a");
4487 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4488 pic16_emitcode("mov","b,a");
4490 /* sign adjust left side */
4491 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4494 lbl = newiTempLabel(NULL);
4495 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4496 pic16_emitcode("cpl","a");
4497 pic16_emitcode("inc","a");
4498 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4500 /* now the division */
4501 pic16_emitcode("div","ab");
4502 /* we are interested in the lower order
4504 pic16_emitcode("mov","b,a");
4505 lbl = newiTempLabel(NULL);
4506 pic16_emitcode("pop","acc");
4507 /* if there was an over flow we don't
4508 adjust the sign of the result */
4509 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4510 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4512 pic16_emitcode("clr","a");
4513 pic16_emitcode("subb","a,b");
4514 pic16_emitcode("mov","b,a");
4515 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4517 /* now we are done */
4518 pic16_aopPut(AOP(result),"b",0);
4520 pic16_emitcode("mov","c,b.7");
4521 pic16_emitcode("subb","a,acc");
4524 pic16_aopPut(AOP(result),"a",offset++);
4528 /*-----------------------------------------------------------------*/
4529 /* genDiv - generates code for division */
4530 /*-----------------------------------------------------------------*/
4531 static void genDiv (iCode *ic)
4533 operand *left = IC_LEFT(ic);
4534 operand *right = IC_RIGHT(ic);
4535 operand *result= IC_RESULT(ic);
4538 /* Division is a very lengthy algorithm, so it is better
4539 * to call support routines than inlining algorithm.
4540 * Division functions written here just in case someone
4541 * wants to inline and not use the support libraries -- VR */
4545 /* assign the amsops */
4546 pic16_aopOp (left,ic,FALSE);
4547 pic16_aopOp (right,ic,FALSE);
4548 pic16_aopOp (result,ic,TRUE);
4550 /* special cases first */
4552 if (AOP_TYPE(left) == AOP_CRY &&
4553 AOP_TYPE(right)== AOP_CRY) {
4554 genDivbits(left,right,result);
4558 /* if both are of size == 1 */
4559 if (AOP_SIZE(left) == 1 &&
4560 AOP_SIZE(right) == 1 ) {
4561 genDivOneByte(left,right,result);
4565 /* should have been converted to function call */
4568 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4569 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4570 pic16_freeAsmop(result,NULL,ic,TRUE);
4573 /*-----------------------------------------------------------------*/
4574 /* genModbits :- modulus of bits */
4575 /*-----------------------------------------------------------------*/
4576 static void genModbits (operand *left,
4584 werror(W_POSSBUG2, __FILE__, __LINE__);
4585 /* the result must be bit */
4586 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4587 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4591 pic16_emitcode("div","ab");
4592 pic16_emitcode("mov","a,b");
4593 pic16_emitcode("rrc","a");
4594 pic16_aopPut(AOP(result),"c",0);
4597 /*-----------------------------------------------------------------*/
4598 /* genModOneByte : 8 bit modulus */
4599 /*-----------------------------------------------------------------*/
4600 static void genModOneByte (operand *left,
4604 sym_link *opetype = operandType(result);
4609 werror(W_POSSBUG2, __FILE__, __LINE__);
4611 /* signed or unsigned */
4612 if (SPEC_USIGN(opetype)) {
4613 /* unsigned is easy */
4614 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4615 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4617 pic16_emitcode("div","ab");
4618 pic16_aopPut(AOP(result),"b",0);
4622 /* signed is a little bit more difficult */
4624 /* save the signs of the operands */
4625 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4628 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4629 pic16_emitcode("push","acc"); /* save it on the stack */
4631 /* now sign adjust for both left & right */
4632 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4635 lbl = newiTempLabel(NULL);
4636 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4637 pic16_emitcode("cpl","a");
4638 pic16_emitcode("inc","a");
4639 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4640 pic16_emitcode("mov","b,a");
4642 /* sign adjust left side */
4643 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4646 lbl = newiTempLabel(NULL);
4647 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4648 pic16_emitcode("cpl","a");
4649 pic16_emitcode("inc","a");
4650 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4652 /* now the multiplication */
4653 pic16_emitcode("div","ab");
4654 /* we are interested in the lower order
4656 lbl = newiTempLabel(NULL);
4657 pic16_emitcode("pop","acc");
4658 /* if there was an over flow we don't
4659 adjust the sign of the result */
4660 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4661 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4663 pic16_emitcode("clr","a");
4664 pic16_emitcode("subb","a,b");
4665 pic16_emitcode("mov","b,a");
4666 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4668 /* now we are done */
4669 pic16_aopPut(AOP(result),"b",0);
4673 /*-----------------------------------------------------------------*/
4674 /* genMod - generates code for division */
4675 /*-----------------------------------------------------------------*/
4676 static void genMod (iCode *ic)
4678 operand *left = IC_LEFT(ic);
4679 operand *right = IC_RIGHT(ic);
4680 operand *result= IC_RESULT(ic);
4684 /* assign the amsops */
4685 pic16_aopOp (left,ic,FALSE);
4686 pic16_aopOp (right,ic,FALSE);
4687 pic16_aopOp (result,ic,TRUE);
4689 /* special cases first */
4691 if (AOP_TYPE(left) == AOP_CRY &&
4692 AOP_TYPE(right)== AOP_CRY) {
4693 genModbits(left,right,result);
4697 /* if both are of size == 1 */
4698 if (AOP_SIZE(left) == 1 &&
4699 AOP_SIZE(right) == 1 ) {
4700 genModOneByte(left,right,result);
4704 /* should have been converted to function call */
4708 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4709 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4710 pic16_freeAsmop(result,NULL,ic,TRUE);
4713 /*-----------------------------------------------------------------*/
4714 /* genIfxJump :- will create a jump depending on the ifx */
4715 /*-----------------------------------------------------------------*/
4717 note: May need to add parameter to indicate when a variable is in bit space.
4719 static void genIfxJump (iCode *ic, char *jval)
4723 /* if true label then we jump if condition
4725 if ( IC_TRUE(ic) ) {
4727 if(strcmp(jval,"a") == 0)
4729 else if (strcmp(jval,"c") == 0)
4732 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4733 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4736 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4737 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4741 /* false label is present */
4742 if(strcmp(jval,"a") == 0)
4744 else if (strcmp(jval,"c") == 0)
4747 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4748 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4751 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4752 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4757 /* mark the icode as generated */
4761 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4765 /* if true label then we jump if condition
4767 if ( IC_TRUE(ic) ) {
4768 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4769 pic16_emitpcode(POC_BTFSC, jop);
4771 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4772 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4775 /* false label is present */
4776 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4777 pic16_emitpcode(POC_BTFSS, jop);
4779 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4780 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4784 /* mark the icode as generated */
4791 /*-----------------------------------------------------------------*/
4793 /*-----------------------------------------------------------------*/
4794 static void genSkip(iCode *ifx,int status_bit)
4796 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4800 if ( IC_TRUE(ifx) ) {
4801 switch(status_bit) {
4816 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4817 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4821 switch(status_bit) {
4835 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4836 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4843 /*-----------------------------------------------------------------*/
4845 /*-----------------------------------------------------------------*/
4846 static void genSkipc(resolvedIfx *rifx)
4848 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4858 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4859 rifx->generated = 1;
4862 #if !(USE_SIMPLE_GENCMP)
4863 /*-----------------------------------------------------------------*/
4865 /*-----------------------------------------------------------------*/
4866 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4868 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4873 if( (rifx->condition ^ invert_condition) & 1)
4878 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4879 rifx->generated = 1;
4884 /*-----------------------------------------------------------------*/
4886 /*-----------------------------------------------------------------*/
4887 static void genSkipz(iCode *ifx, int condition)
4898 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4900 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4903 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4905 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4910 #if !(USE_SIMPLE_GENCMP)
4911 /*-----------------------------------------------------------------*/
4913 /*-----------------------------------------------------------------*/
4914 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4920 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4922 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4925 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4926 rifx->generated = 1;
4931 /*-----------------------------------------------------------------*/
4932 /* genChkZeroes :- greater or less than comparison */
4933 /* For each byte in a literal that is zero, inclusive or the */
4934 /* the corresponding byte in the operand with W */
4935 /* returns true if any of the bytes are zero */
4936 /*-----------------------------------------------------------------*/
4937 static int genChkZeroes(operand *op, int lit, int size)
4944 i = (lit >> (size*8)) & 0xff;
4948 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4950 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4960 /*-----------------------------------------------------------------*/
4961 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4962 /* aop (if it's NOT a literal) or from lit (if */
4963 /* aop is a literal) */
4964 /*-----------------------------------------------------------------*/
4965 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4966 if (aop->type == AOP_LIT) {
4967 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4969 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4973 /*-----------------------------------------------------------------*/
4974 /* genCmp :- greater or less than comparison */
4975 /*-----------------------------------------------------------------*/
4977 #if USE_SIMPLE_GENCMP /* { */
4979 /* genCmp performs a left < right comparison, stores
4980 * the outcome in result (if != NULL) and generates
4981 * control flow code for the ifx (if != NULL).
4983 * This version leaves in sequences like
4984 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4985 * which should be optmized by the peephole
4986 * optimizer - RN 2005-01-01 */
4987 static void genCmp (operand *left,operand *right,
4988 operand *result, iCode *ifx, int sign)
5001 assert (AOP_SIZE(left) == AOP_SIZE(right));
5002 assert (left && right);
5004 size = AOP_SIZE(right) - 1;
5005 mask = (0x100UL << (size*8)) - 1;
5006 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5011 resolveIfx (&rIfx, ifx);
5013 /* handle for special cases */
5014 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5017 /**********************************************************************
5018 * handle bits - bit compares are promoted to int compares seemingly! *
5019 **********************************************************************/
5021 // THIS IS COMPLETELY UNTESTED!
5022 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5023 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5024 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5025 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5028 // 1 < {0,1} is false --> clear C by skipping the next instruction
5029 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5030 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5031 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5032 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5033 emitCLRC; // only skipped for left=0 && right=1
5035 goto correct_result_in_carry;
5039 /*************************************************
5040 * make sure that left is register (or the like) *
5041 *************************************************/
5042 if (!isAOP_REGlike(left)) {
5043 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5044 assert (isAOP_LIT(left));
5045 assert (isAOP_REGlike(right));
5046 // swap left and right
5047 // left < right <==> right > left <==> (right >= left + 1)
5048 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5050 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5051 // MAXVALUE < right? always false
5052 if (performedLt) emitCLRC; else emitSETC;
5053 goto correct_result_in_carry;
5056 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5057 // that's why we handled it above.
5064 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5065 } else if (isAOP_LIT(right)) {
5066 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5069 assert (isAOP_REGlike(left)); // left must be register or the like
5070 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5072 /*************************************************
5073 * special cases go here *
5074 *************************************************/
5076 if (isAOP_LIT(right)) {
5078 // unsigned comparison to a literal
5079 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5081 // unsigned left < 0? always false
5082 if (performedLt) emitCLRC; else emitSETC;
5083 goto correct_result_in_carry;
5086 // signed comparison to a literal
5087 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5088 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5089 // signed left < 0x80000000? always false
5090 if (performedLt) emitCLRC; else emitSETC;
5091 goto correct_result_in_carry;
5092 } else if (lit == 0) {
5093 // compare left < 0; set CARRY if SIGNBIT(left) is set
5094 if (performedLt) emitSETC; else emitCLRC;
5095 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5096 if (performedLt) emitCLRC; else emitSETC;
5097 goto correct_result_in_carry;
5100 } // right is literal
5102 /*************************************************
5103 * perform a general case comparison *
5104 * make sure we get CARRY==1 <==> left >= right *
5105 *************************************************/
5106 // compare most significant bytes
5107 //DEBUGpc ("comparing bytes at offset %d", size);
5109 // unsigned comparison
5110 mov2w_regOrLit (AOP(right), lit, size);
5111 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5113 // signed comparison
5114 // (add 2^n to both operands then perform an unsigned comparison)
5115 if (isAOP_LIT(right)) {
5116 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5117 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5119 if (litbyte == 0x80) {
5120 // left >= 0x80 -- always true, but more bytes to come
5121 pic16_mov2w (AOP(left), size);
5122 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5125 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5126 pic16_mov2w (AOP(left), size);
5127 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5128 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5131 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5132 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5133 pic16_mov2w (AOP(left), size);
5134 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5135 pic16_emitpcode (POC_MOVWF, pctemp);
5136 pic16_mov2w (AOP(right), size);
5137 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5138 pic16_emitpcode (POC_SUBFW, pctemp);
5139 //pic16_popReleaseTempReg(pctemp, 1);
5143 // compare remaining bytes (treat as unsigned case from above)
5144 templbl = newiTempLabel ( NULL );
5147 //DEBUGpc ("comparing bytes at offset %d", offs);
5148 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5149 mov2w_regOrLit (AOP(right), lit, offs);
5150 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5152 pic16_emitpLabel (templbl->key);
5153 goto result_in_carry;
5157 /****************************************************
5158 * now CARRY contains the result of the comparison: *
5159 * SUBWF sets CARRY iff *
5160 * F-W >= 0 <==> F >= W <==> !(F < W) *
5161 * (F=left, W=right) *
5162 ****************************************************/
5165 if (result && AOP_TYPE(result) != AOP_CRY) {
5166 // value will be stored
5169 // value wil only be used in the following genSkipc()
5170 rIfx.condition ^= 1;
5174 correct_result_in_carry:
5176 // assign result to variable (if neccessary)
5177 if (result && AOP_TYPE(result) != AOP_CRY) {
5178 //DEBUGpc ("assign result");
5179 size = AOP_SIZE(result);
5181 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5183 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5186 // perform conditional jump
5188 //DEBUGpc ("generate control flow");
5197 static void genCmp (operand *left,operand *right,
5198 operand *result, iCode *ifx, int sign)
5200 int size; //, offset = 0 ;
5201 unsigned long lit = 0L,i = 0;
5202 resolvedIfx rFalseIfx;
5203 // resolvedIfx rTrueIfx;
5205 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5208 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5209 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5215 resolveIfx(&rFalseIfx,ifx);
5216 truelbl = newiTempLabel(NULL);
5217 size = max(AOP_SIZE(left),AOP_SIZE(right));
5219 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5223 /* if literal is on the right then swap with left */
5224 if ((AOP_TYPE(right) == AOP_LIT)) {
5225 operand *tmp = right ;
5226 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5227 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5230 lit = (lit - 1) & mask;
5233 rFalseIfx.condition ^= 1;
5236 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5237 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5241 //if(IC_TRUE(ifx) == NULL)
5242 /* if left & right are bit variables */
5243 if (AOP_TYPE(left) == AOP_CRY &&
5244 AOP_TYPE(right) == AOP_CRY ) {
5245 assert (0 && "bit variables used in genCmp");
5246 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5247 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5249 /* subtract right from left if at the
5250 end the carry flag is set then we know that
5251 left is greater than right */
5253 symbol *lbl = newiTempLabel(NULL);
5256 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5257 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5261 if(AOP_TYPE(right) == AOP_LIT) {
5263 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5265 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5272 genSkipCond(&rFalseIfx,left,size-1,7);
5274 /* no need to compare to 0...*/
5275 /* NOTE: this is a de-generate compare that most certainly
5276 * creates some dead code. */
5277 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5279 if(ifx) ifx->generated = 1;
5286 //i = (lit >> (size*8)) & 0xff;
5287 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5289 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5291 i = ((0-lit) & 0xff);
5294 /* lit is 0x7f, all signed chars are less than
5295 * this except for 0x7f itself */
5296 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5297 genSkipz2(&rFalseIfx,0);
5299 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5300 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5301 genSkipc(&rFalseIfx);
5306 genSkipz2(&rFalseIfx,1);
5308 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5309 genSkipc(&rFalseIfx);
5313 if(ifx) ifx->generated = 1;
5317 /* chars are out of the way. now do ints and longs */
5320 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5327 genSkipCond(&rFalseIfx,left,size,7);
5328 if(ifx) ifx->generated = 1;
5333 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5335 //rFalseIfx.condition ^= 1;
5336 //genSkipCond(&rFalseIfx,left,size,7);
5337 //rFalseIfx.condition ^= 1;
5339 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5340 if(rFalseIfx.condition)
5341 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5343 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5345 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5346 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5347 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5350 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5352 if(rFalseIfx.condition) {
5354 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5360 genSkipc(&rFalseIfx);
5361 pic16_emitpLabel(truelbl->key);
5362 if(ifx) ifx->generated = 1;
5369 if( (lit & 0xff) == 0) {
5370 /* lower byte is zero */
5371 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5372 i = ((lit >> 8) & 0xff) ^0x80;
5373 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5374 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5375 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5376 genSkipc(&rFalseIfx);
5379 if(ifx) ifx->generated = 1;
5384 /* Special cases for signed longs */
5385 if( (lit & 0xffffff) == 0) {
5386 /* lower byte is zero */
5387 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5388 i = ((lit >> 8*3) & 0xff) ^0x80;
5389 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5390 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5391 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5392 genSkipc(&rFalseIfx);
5395 if(ifx) ifx->generated = 1;
5403 if(lit & (0x80 << (size*8))) {
5404 /* lit is negative */
5405 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5407 //genSkipCond(&rFalseIfx,left,size,7);
5409 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5411 if(rFalseIfx.condition)
5412 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5414 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5418 /* lit is positive */
5419 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5420 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5421 if(rFalseIfx.condition)
5422 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5424 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5429 This works, but is only good for ints.
5430 It also requires a "known zero" register.
5431 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5432 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5433 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5434 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5435 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5436 genSkipc(&rFalseIfx);
5438 pic16_emitpLabel(truelbl->key);
5439 if(ifx) ifx->generated = 1;
5443 /* There are no more special cases, so perform a general compare */
5445 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5446 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5450 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5452 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5454 //rFalseIfx.condition ^= 1;
5455 genSkipc(&rFalseIfx);
5457 pic16_emitpLabel(truelbl->key);
5459 if(ifx) ifx->generated = 1;
5466 /* sign is out of the way. So now do an unsigned compare */
5467 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5470 /* General case - compare to an unsigned literal on the right.*/
5472 i = (lit >> (size*8)) & 0xff;
5473 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5474 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5476 i = (lit >> (size*8)) & 0xff;
5479 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5481 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5483 /* this byte of the lit is zero,
5484 *if it's not the last then OR in the variable */
5486 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5491 pic16_emitpLabel(lbl->key);
5492 // pic16_emitpLabel(truelbl->key);
5493 //if(emitFinalCheck)
5494 genSkipc(&rFalseIfx);
5496 pic16_emitpLabel(truelbl->key);
5498 if(ifx) ifx->generated = 1;
5505 if(AOP_TYPE(left) == AOP_LIT) {
5506 //symbol *lbl = newiTempLabel(NULL);
5508 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5511 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5514 if((lit == 0) && (sign == 0)){
5517 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5519 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5521 genSkipz2(&rFalseIfx,0);
5522 if(ifx) ifx->generated = 1;
5529 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5530 /* degenerate compare can never be true */
5531 if(rFalseIfx.condition == 0)
5532 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5534 if(ifx) ifx->generated = 1;
5539 /* signed comparisons to a literal byte */
5541 int lp1 = (lit+1) & 0xff;
5543 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5546 rFalseIfx.condition ^= 1;
5547 genSkipCond(&rFalseIfx,right,0,7);
5550 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5551 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5552 genSkipz2(&rFalseIfx,1);
5555 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5556 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5557 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5558 rFalseIfx.condition ^= 1;
5559 genSkipc(&rFalseIfx);
5563 /* unsigned comparisons to a literal byte */
5565 switch(lit & 0xff ) {
5567 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5568 genSkipz2(&rFalseIfx,0);
5571 rFalseIfx.condition ^= 1;
5572 genSkipCond(&rFalseIfx,right,0,7);
5576 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5577 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5578 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5579 rFalseIfx.condition ^= 1;
5580 if (AOP_TYPE(result) == AOP_CRY)
5581 genSkipc(&rFalseIfx);
5583 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5584 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5590 if(ifx) ifx->generated = 1;
5591 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5597 /* Size is greater than 1 */
5605 /* this means lit = 0xffffffff, or -1 */
5608 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5609 rFalseIfx.condition ^= 1;
5610 genSkipCond(&rFalseIfx,right,size,7);
5611 if(ifx) ifx->generated = 1;
5613 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5622 if(rFalseIfx.condition) {
5623 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5624 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5627 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5629 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5633 if(rFalseIfx.condition) {
5634 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5635 pic16_emitpLabel(truelbl->key);
5637 rFalseIfx.condition ^= 1;
5638 genSkipCond(&rFalseIfx,right,s,7);
5641 if(ifx) ifx->generated = 1;
5643 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5649 if((size == 1) && (0 == (lp1&0xff))) {
5650 /* lower byte of signed word is zero */
5651 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5652 i = ((lp1 >> 8) & 0xff) ^0x80;
5653 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5654 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5655 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5657 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5659 if(ifx) ifx->generated = 1;
5662 rFalseIfx.condition ^= 1;
5663 genSkipc(&rFalseIfx);
5664 if(ifx) ifx->generated = 1;
5670 if(lit & (0x80 << (size*8))) {
5671 /* Lit is less than zero */
5672 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5673 //rFalseIfx.condition ^= 1;
5674 //genSkipCond(&rFalseIfx,left,size,7);
5675 //rFalseIfx.condition ^= 1;
5676 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5677 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5679 if(rFalseIfx.condition)
5680 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5682 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5686 /* Lit is greater than or equal to zero */
5687 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5688 //rFalseIfx.condition ^= 1;
5689 //genSkipCond(&rFalseIfx,right,size,7);
5690 //rFalseIfx.condition ^= 1;
5692 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5693 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5695 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5696 if(rFalseIfx.condition)
5697 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5699 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5703 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5704 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5708 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5710 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5712 rFalseIfx.condition ^= 1;
5713 //rFalseIfx.condition = 1;
5714 genSkipc(&rFalseIfx);
5716 pic16_emitpLabel(truelbl->key);
5718 if(ifx) ifx->generated = 1;
5721 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5728 /* compare word or long to an unsigned literal on the right.*/
5733 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5736 break; /* handled above */
5739 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5741 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5742 genSkipz2(&rFalseIfx,0);
5746 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5748 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5751 if(rFalseIfx.condition)
5752 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5754 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5757 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5758 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5760 rFalseIfx.condition ^= 1;
5761 genSkipc(&rFalseIfx);
5764 pic16_emitpLabel(truelbl->key);
5766 if(ifx) ifx->generated = 1;
5768 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5776 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5777 i = (lit >> (size*8)) & 0xff;
5779 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5780 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5783 i = (lit >> (size*8)) & 0xff;
5786 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5788 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5790 /* this byte of the lit is zero,
5791 * if it's not the last then OR in the variable */
5793 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5798 pic16_emitpLabel(lbl->key);
5800 rFalseIfx.condition ^= 1;
5802 genSkipc(&rFalseIfx);
5806 pic16_emitpLabel(truelbl->key);
5807 if(ifx) ifx->generated = 1;
5809 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5815 /* Compare two variables */
5817 DEBUGpic16_emitcode(";sign","%d",sign);
5821 /* Sigh. thus sucks... */
5825 pctemp = pic16_popGetTempReg(1);
5826 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5827 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5828 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5829 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5830 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5831 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5832 pic16_popReleaseTempReg(pctemp, 1);
5834 /* Signed char comparison */
5835 /* Special thanks to Nikolai Golovchenko for this snippet */
5836 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5837 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5838 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5839 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5840 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5841 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5843 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5844 genSkipc(&rFalseIfx);
5846 if(ifx) ifx->generated = 1;
5848 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5856 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5857 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5861 /* The rest of the bytes of a multi-byte compare */
5865 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5868 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5869 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5874 pic16_emitpLabel(lbl->key);
5876 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5877 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5878 (AOP_TYPE(result) == AOP_REG)) {
5879 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5880 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5882 genSkipc(&rFalseIfx);
5884 //genSkipc(&rFalseIfx);
5885 if(ifx) ifx->generated = 1;
5888 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5896 if ((AOP_TYPE(result) != AOP_CRY)
5897 && AOP_SIZE(result)) {
5898 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5900 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5902 pic16_outBitC(result);
5904 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5905 /* if the result is used in the next
5906 ifx conditional branch then generate
5907 code a little differently */
5909 genIfxJump (ifx,"c");
5911 pic16_outBitC(result);
5912 /* leave the result in acc */
5917 #elif 0 /* VR version of genCmp() */ /* } else { */
5919 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5920 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5921 operand *result, int offset, int invert_op)
5925 /* check condition, > or < ?? */
5926 if(rIfx->condition != 0)invert_op ^= 1;
5928 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5930 if(!ifx)invert_op ^= 1;
5932 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5933 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5936 if(!invert_op)return POC_CPFSGT;
5937 else return POC_CPFSLT;
5940 static int compareAopfirstpass=1;
5942 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5943 operand *oper, int offset, operand *result,
5944 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5950 /* invert if there is a result to be loaded, in order to fit,
5951 * SETC/CLRC sequence */
5952 if(AOP_SIZE(result))invert_op ^= 1;
5954 // if(sign && !offset)invert_op ^= 1;
5956 // if(sign)invert_op ^= 1;
5958 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5960 if(AOP_SIZE(result) && compareAopfirstpass) {
5963 pic16_emitpcode(POC_SETF, pcop2);
5968 pic16_emitpcode(POC_CLRF, pcop2);
5974 compareAopfirstpass = 0;
5976 /* there is a bug when comparing operands with size > 1,
5977 * because higher bytes can be equal and test should be performed
5978 * to the next lower byte, current algorithm, considers operands
5979 * inequal in these cases! -- VR 20041107 */
5983 pic16_emitpcode(op, pcop);
5985 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5988 if((!sign || !offset) && AOP_SIZE(result)) {
5991 pic16_emitpcode(POC_CLRF, pcop2);
5996 pic16_emitpcode(POC_SETF, pcop2);
6001 /* don't emit final branch (offset == 0) */
6005 pic16_emitpcode(POC_RRCF, pcop2);
6007 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6010 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6011 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6012 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6014 truelbl = newiTempLabel( NULL );
6015 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6016 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6017 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6019 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6020 pic16_emitpLabel(truelbl->key);
6022 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6027 static void genCmp (operand *left, operand *right,
6028 operand *result, iCode *ifx, int sign)
6032 resolvedIfx rFalseIfx;
6033 symbol *falselbl, *tlbl;
6037 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6039 resolveIfx(&rFalseIfx, ifx);
6040 size = max(AOP_SIZE(left), AOP_SIZE(right));
6042 /* if left & right are bit variables */
6043 if(AOP_TYPE(left) == AOP_CRY
6044 && AOP_TYPE(right) == AOP_CRY ) {
6046 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6047 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6049 werror(W_POSSBUG2, __FILE__, __LINE__);
6053 /* if literal is on the right then swap with left */
6054 if((AOP_TYPE(right) == AOP_LIT)) {
6055 operand *tmp = right ;
6056 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6058 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6060 // lit = (lit - 1) & mask;
6063 rFalseIfx.condition ^= 1; /* reverse compare */
6065 if ((AOP_TYPE(left) == AOP_LIT)) {
6066 /* float compares are handled by support functions */
6067 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6070 /* actual comparing algorithm */
6071 // size = AOP_SIZE( right );
6073 falselbl = newiTempLabel( NULL );
6074 if(AOP_TYPE(left) == AOP_LIT) {
6075 /* compare to literal */
6076 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6079 pCodeOp *pct, *pct2;
6082 /* signed compare */
6083 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6085 pct = pic16_popCopyReg(&pic16_pc_prodl);
6086 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6087 tlbl = newiTempLabel( NULL );
6089 /* first compare signs:
6090 * a. if both are positive, compare just like unsigned
6091 * b. if both are negative, invert cmpop, compare just like unsigned
6092 * c. if different signs, determine the result directly */
6098 tlbl1 = newiTempLabel( NULL );
6099 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6103 /* literal is zero or positive:
6104 * a. if carry is zero, too, continue compare,
6105 * b. if carry is set, then continue depending on cmpop ^ condition:
6106 * 1. '<' return false (literal < variable),
6107 * 2. '>' return true (literal > variable) */
6108 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6109 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6112 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6113 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6117 /* literal is negative:
6118 * a. if carry is set, too, continue compare,
6119 * b. if carry is zero, then continue depending on cmpop ^ condition:
6120 * 1. '<' return true (literal < variable),
6121 * 2. '>' return false (literal > variable) */
6122 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6123 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6125 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6126 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6131 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6133 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6134 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6139 pic16_emitpLabel( tlbl1->key );
6142 compareAopfirstpass=1;
6143 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6144 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6145 // pic16_emitpcode(POC_MOVWF, pct);
6147 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6148 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6149 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6150 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6154 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6155 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6156 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6157 // pic16_emitpcode(POC_MOVWF, pct);
6159 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6160 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6161 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6162 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6163 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6166 if(ifx)ifx->generated = 1;
6168 if(AOP_SIZE(result)) {
6169 pic16_emitpLabel(tlbl->key);
6170 pic16_emitpLabel(falselbl->key);
6171 pic16_outBitOp( result, pct2 );
6173 pic16_emitpLabel(tlbl->key);
6177 /* unsigned compare */
6178 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6180 compareAopfirstpass=1;
6183 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6184 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6187 if(ifx)ifx->generated = 1;
6189 if(AOP_SIZE(result)) {
6190 pic16_emitpLabel(falselbl->key);
6191 pic16_outBitC( result );
6196 /* compare registers */
6197 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6201 pCodeOp *pct, *pct2;
6203 /* signed compare */
6204 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6206 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6207 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6208 tlbl = newiTempLabel( NULL );
6210 compareAopfirstpass=1;
6213 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6214 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6215 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6216 pic16_emitpcode(POC_MOVWF, pct);
6218 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6219 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6220 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6222 /* WREG already holds left + 0x80 */
6223 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6226 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6227 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6228 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6229 pic16_emitpcode(POC_MOVWF, pct);
6231 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6232 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6233 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6235 /* WREG already holds left + 0x80 */
6236 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6237 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6240 if(ifx)ifx->generated = 1;
6242 if(AOP_SIZE(result)) {
6243 pic16_emitpLabel(tlbl->key);
6244 pic16_emitpLabel(falselbl->key);
6245 pic16_outBitOp( result, pct2 );
6247 pic16_emitpLabel(tlbl->key);
6251 /* unsigned compare */
6252 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6254 compareAopfirstpass=1;
6257 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6258 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6262 if(ifx)ifx->generated = 1;
6263 if(AOP_SIZE(result)) {
6265 pic16_emitpLabel(falselbl->key);
6266 pic16_outBitC( result );
6277 /*-----------------------------------------------------------------*/
6278 /* genCmpGt :- greater than comparison */
6279 /*-----------------------------------------------------------------*/
6280 static void genCmpGt (iCode *ic, iCode *ifx)
6282 operand *left, *right, *result;
6283 sym_link *letype , *retype;
6289 right= IC_RIGHT(ic);
6290 result = IC_RESULT(ic);
6292 letype = getSpec(operandType(left));
6293 retype =getSpec(operandType(right));
6294 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6295 /* assign the amsops */
6296 pic16_aopOp (left,ic,FALSE);
6297 pic16_aopOp (right,ic,FALSE);
6298 pic16_aopOp (result,ic,TRUE);
6300 genCmp(right, left, result, ifx, sign);
6302 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6303 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6304 pic16_freeAsmop(result,NULL,ic,TRUE);
6307 /*-----------------------------------------------------------------*/
6308 /* genCmpLt - less than comparisons */
6309 /*-----------------------------------------------------------------*/
6310 static void genCmpLt (iCode *ic, iCode *ifx)
6312 operand *left, *right, *result;
6313 sym_link *letype , *retype;
6319 right= IC_RIGHT(ic);
6320 result = IC_RESULT(ic);
6322 letype = getSpec(operandType(left));
6323 retype =getSpec(operandType(right));
6324 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6326 /* assign the amsops */
6327 pic16_aopOp (left,ic,FALSE);
6328 pic16_aopOp (right,ic,FALSE);
6329 pic16_aopOp (result,ic,TRUE);
6331 genCmp(left, right, result, ifx, sign);
6333 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6334 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6335 pic16_freeAsmop(result,NULL,ic,TRUE);
6340 // FIXME reenable literal optimisation when the pic16 port is stable
6342 /*-----------------------------------------------------------------*/
6343 /* genc16bit2lit - compare a 16 bit value to a literal */
6344 /*-----------------------------------------------------------------*/
6345 static void genc16bit2lit(operand *op, int lit, int offset)
6349 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6350 if( (lit&0xff) == 0)
6355 switch( BYTEofLONG(lit,i)) {
6357 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6360 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6363 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6366 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6367 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6372 switch( BYTEofLONG(lit,i)) {
6374 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6378 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6382 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6385 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6387 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6396 /*-----------------------------------------------------------------*/
6397 /* gencjneshort - compare and jump if not equal */
6398 /*-----------------------------------------------------------------*/
6399 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6401 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6403 int res_offset = 0; /* the result may be a different size then left or right */
6404 int res_size = AOP_SIZE(result);
6406 symbol *lbl, *lbl_done;
6408 unsigned long lit = 0L;
6409 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6411 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6412 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6414 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6415 resolveIfx(&rIfx,ifx);
6416 lbl = newiTempLabel(NULL);
6417 lbl_done = newiTempLabel(NULL);
6420 /* if the left side is a literal or
6421 if the right is in a pointer register and left
6423 if ((AOP_TYPE(left) == AOP_LIT) ||
6424 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6429 if(AOP_TYPE(right) == AOP_LIT)
6430 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6432 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6433 preserve_result = 1;
6435 if(result && !preserve_result)
6438 for(i = 0; i < AOP_SIZE(result); i++)
6439 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6443 /* if the right side is a literal then anything goes */
6444 if (AOP_TYPE(right) == AOP_LIT &&
6445 AOP_TYPE(left) != AOP_DIR ) {
6448 genc16bit2lit(left, lit, 0);
6450 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6453 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6456 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6457 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6459 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6463 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6465 if(res_offset < res_size-1)
6473 /* if the right side is in a register or in direct space or
6474 if the left is a pointer register & right is not */
6475 else if (AOP_TYPE(right) == AOP_REG ||
6476 AOP_TYPE(right) == AOP_DIR ||
6477 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6478 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6479 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6480 int lbl_key = lbl->key;
6483 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6484 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6486 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6487 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6488 __FUNCTION__,__LINE__);
6492 /* switch(size) { */
6494 /* genc16bit2lit(left, lit, 0); */
6496 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6501 if((AOP_TYPE(left) == AOP_DIR) &&
6502 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6504 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6505 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6507 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6509 switch (lit & 0xff) {
6511 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6514 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6515 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6516 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6520 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6521 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6522 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6523 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6527 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6528 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6533 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6536 if(AOP_TYPE(result) == AOP_CRY) {
6537 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6542 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6544 /* fix me. probably need to check result size too */
6545 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6550 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6551 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6558 if(res_offset < res_size-1)
6563 } else if(AOP_TYPE(right) == AOP_REG &&
6564 AOP_TYPE(left) != AOP_DIR){
6567 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6568 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6569 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6574 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6576 if(res_offset < res_size-1)
6581 /* right is a pointer reg need both a & b */
6583 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6585 pic16_emitcode("mov","b,%s",l);
6586 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6587 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6592 if(result && preserve_result)
6595 for(i = 0; i < AOP_SIZE(result); i++)
6596 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6599 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6601 if(result && preserve_result)
6602 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6605 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6607 pic16_emitpLabel(lbl->key);
6609 if(result && preserve_result)
6612 for(i = 0; i < AOP_SIZE(result); i++)
6613 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6615 pic16_emitpLabel(lbl_done->key);
6618 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6626 /*-----------------------------------------------------------------*/
6627 /* gencjne - compare and jump if not equal */
6628 /*-----------------------------------------------------------------*/
6629 static void gencjne(operand *left, operand *right, iCode *ifx)
6631 symbol *tlbl = newiTempLabel(NULL);
6633 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6634 gencjneshort(left, right, lbl);
6636 pic16_emitcode("mov","a,%s",one);
6637 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6638 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6639 pic16_emitcode("clr","a");
6640 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6642 pic16_emitpLabel(lbl->key);
6643 pic16_emitpLabel(tlbl->key);
6649 /*-----------------------------------------------------------------*/
6650 /* is_LitOp - check if operand has to be treated as literal */
6651 /*-----------------------------------------------------------------*/
6652 static bool is_LitOp(operand *op)
6654 return ((AOP_TYPE(op) == AOP_LIT)
6655 || ( (AOP_TYPE(op) == AOP_PCODE)
6656 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6657 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6660 /*-----------------------------------------------------------------*/
6661 /* is_LitAOp - check if operand has to be treated as literal */
6662 /*-----------------------------------------------------------------*/
6663 static bool is_LitAOp(asmop *aop)
6665 return ((aop->type == AOP_LIT)
6666 || ( (aop->type == AOP_PCODE)
6667 && ( (aop->aopu.pcop->type == PO_LITERAL)
6668 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6673 /*-----------------------------------------------------------------*/
6674 /* genCmpEq - generates code for equal to */
6675 /*-----------------------------------------------------------------*/
6676 static void genCmpEq (iCode *ic, iCode *ifx)
6678 operand *left, *right, *result;
6679 symbol *falselbl = newiTempLabel(NULL);
6680 symbol *donelbl = newiTempLabel(NULL);
6682 int preserve_result = 0;
6683 int generate_result = 0;
6685 unsigned long lit = -1;
6689 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6690 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6691 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6693 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6695 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6697 werror(W_POSSBUG2, __FILE__, __LINE__);
6698 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6699 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6703 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6705 operand *tmp = right ;
6710 if (AOP_TYPE(right) == AOP_LIT) {
6711 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6714 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6715 preserve_result = 1;
6717 if(result && AOP_SIZE(result))
6718 generate_result = 1;
6720 if(generate_result && !preserve_result)
6722 for(i = 0; i < AOP_SIZE(result); i++)
6723 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6726 for(i=0; i < AOP_SIZE(left); i++)
6728 if(AOP_TYPE(left) != AOP_ACC)
6731 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6733 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6735 if(is_LitOp(right)) {
6736 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6737 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6740 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6742 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6747 if(generate_result && preserve_result)
6749 for(i = 0; i < AOP_SIZE(result); i++)
6750 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6754 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6756 if(generate_result && preserve_result)
6757 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6759 if(ifx && IC_TRUE(ifx))
6760 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6762 if(ifx && IC_FALSE(ifx))
6763 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6765 pic16_emitpLabel(falselbl->key);
6769 if(ifx && IC_FALSE(ifx))
6770 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6772 if(generate_result && preserve_result)
6774 for(i = 0; i < AOP_SIZE(result); i++)
6775 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6778 pic16_emitpLabel(donelbl->key);
6784 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6785 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6786 pic16_freeAsmop(result,NULL,ic,TRUE);
6792 // old version kept for reference
6794 /*-----------------------------------------------------------------*/
6795 /* genCmpEq - generates code for equal to */
6796 /*-----------------------------------------------------------------*/
6797 static void genCmpEq (iCode *ic, iCode *ifx)
6799 operand *left, *right, *result;
6800 unsigned long lit = 0L;
6802 symbol *falselbl = newiTempLabel(NULL);
6805 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6808 DEBUGpic16_emitcode ("; ifx is non-null","");
6810 DEBUGpic16_emitcode ("; ifx is null","");
6812 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6813 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6814 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6816 size = max(AOP_SIZE(left),AOP_SIZE(right));
6818 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6820 /* if literal, literal on the right or
6821 if the right is in a pointer register and left
6823 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6824 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6825 operand *tmp = right ;
6831 if(ifx && !AOP_SIZE(result)){
6833 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6834 /* if they are both bit variables */
6835 if (AOP_TYPE(left) == AOP_CRY &&
6836 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6837 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6838 if(AOP_TYPE(right) == AOP_LIT){
6839 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6841 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6842 pic16_emitcode("cpl","c");
6843 } else if(lit == 1L) {
6844 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6846 pic16_emitcode("clr","c");
6848 /* AOP_TYPE(right) == AOP_CRY */
6850 symbol *lbl = newiTempLabel(NULL);
6851 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6852 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6853 pic16_emitcode("cpl","c");
6854 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6856 /* if true label then we jump if condition
6858 tlbl = newiTempLabel(NULL);
6859 if ( IC_TRUE(ifx) ) {
6860 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6861 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6863 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6864 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6866 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6869 /* left and right are both bit variables, result is carry */
6872 resolveIfx(&rIfx,ifx);
6874 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6875 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6876 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6877 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6882 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6884 /* They're not both bit variables. Is the right a literal? */
6885 if(AOP_TYPE(right) == AOP_LIT) {
6886 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6891 switch(lit & 0xff) {
6893 if ( IC_TRUE(ifx) ) {
6894 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6896 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6898 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6899 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6903 if ( IC_TRUE(ifx) ) {
6904 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6906 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6908 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6909 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6913 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6915 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6920 /* end of size == 1 */
6924 genc16bit2lit(left,lit,offset);
6927 /* end of size == 2 */
6932 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6933 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6934 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6935 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6938 /* search for patterns that can be optimized */
6940 genc16bit2lit(left,lit,0);
6944 emitSKPZ; // if hi word unequal
6946 emitSKPNZ; // if hi word equal
6948 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6949 genc16bit2lit(left,lit,2);
6952 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6953 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6957 pic16_emitpLabel(falselbl->key);
6966 } else if(AOP_TYPE(right) == AOP_CRY ) {
6967 /* we know the left is not a bit, but that the right is */
6968 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6969 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6970 pic16_popGet(AOP(right),offset));
6971 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6973 /* if the two are equal, then W will be 0 and the Z bit is set
6974 * we could test Z now, or go ahead and check the high order bytes if
6975 * the variable we're comparing is larger than a byte. */
6978 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6980 if ( IC_TRUE(ifx) ) {
6982 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6983 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6986 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6987 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6991 /* They're both variables that are larger than bits */
6994 tlbl = newiTempLabel(NULL);
6997 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6998 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7000 if ( IC_TRUE(ifx) ) {
7004 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7006 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7007 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7011 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7014 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7015 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7020 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7022 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7023 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7027 if(s>1 && IC_TRUE(ifx)) {
7028 pic16_emitpLabel(tlbl->key);
7029 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7033 /* mark the icode as generated */
7038 /* if they are both bit variables */
7039 if (AOP_TYPE(left) == AOP_CRY &&
7040 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7041 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7042 if(AOP_TYPE(right) == AOP_LIT){
7043 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7045 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7046 pic16_emitcode("cpl","c");
7047 } else if(lit == 1L) {
7048 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7050 pic16_emitcode("clr","c");
7052 /* AOP_TYPE(right) == AOP_CRY */
7054 symbol *lbl = newiTempLabel(NULL);
7055 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7056 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7057 pic16_emitcode("cpl","c");
7058 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7061 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7062 pic16_outBitC(result);
7066 genIfxJump (ifx,"c");
7069 /* if the result is used in an arithmetic operation
7070 then put the result in place */
7071 pic16_outBitC(result);
7074 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7075 gencjne(left,right,result,ifx);
7078 gencjne(left,right,newiTempLabel(NULL));
7080 if(IC_TRUE(ifx)->key)
7081 gencjne(left,right,IC_TRUE(ifx)->key);
7083 gencjne(left,right,IC_FALSE(ifx)->key);
7087 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7088 pic16_aopPut(AOP(result),"a",0);
7093 genIfxJump (ifx,"a");
7097 /* if the result is used in an arithmetic operation
7098 then put the result in place */
7100 if (AOP_TYPE(result) != AOP_CRY)
7101 pic16_outAcc(result);
7103 /* leave the result in acc */
7107 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7108 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7109 pic16_freeAsmop(result,NULL,ic,TRUE);
7113 /*-----------------------------------------------------------------*/
7114 /* ifxForOp - returns the icode containing the ifx for operand */
7115 /*-----------------------------------------------------------------*/
7116 static iCode *ifxForOp ( operand *op, iCode *ic )
7120 /* if true symbol then needs to be assigned */
7121 if (IS_TRUE_SYMOP(op))
7124 /* if this has register type condition and
7125 the next instruction is ifx with the same operand
7126 and live to of the operand is upto the ifx only then */
7128 && ic->next->op == IFX
7129 && IC_COND(ic->next)->key == op->key
7130 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7132 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7138 ic->next->op == IFX &&
7139 IC_COND(ic->next)->key == op->key) {
7140 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7145 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7147 ic->next->op == IFX)
7148 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7151 ic->next->op == IFX &&
7152 IC_COND(ic->next)->key == op->key) {
7153 DEBUGpic16_emitcode ("; "," key is okay");
7154 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7155 OP_SYMBOL(op)->liveTo,
7160 /* the code below is completely untested
7161 * it just allows ulong2fs.c compile -- VR */
7164 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7165 __FILE__, __FUNCTION__, __LINE__);
7167 /* if this has register type condition and
7168 the next instruction is ifx with the same operand
7169 and live to of the operand is upto the ifx only then */
7171 ic->next->op == IFX &&
7172 IC_COND(ic->next)->key == op->key &&
7173 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7177 ic->next->op == IFX &&
7178 IC_COND(ic->next)->key == op->key) {
7179 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7183 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7184 __FILE__, __FUNCTION__, __LINE__);
7186 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7191 /*-----------------------------------------------------------------*/
7192 /* genAndOp - for && operation */
7193 /*-----------------------------------------------------------------*/
7194 static void genAndOp (iCode *ic)
7196 operand *left,*right, *result;
7201 /* note here that && operations that are in an
7202 if statement are taken away by backPatchLabels
7203 only those used in arthmetic operations remain */
7204 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7205 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7206 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7208 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7210 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7211 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7212 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7214 /* if both are bit variables */
7215 /* if (AOP_TYPE(left) == AOP_CRY && */
7216 /* AOP_TYPE(right) == AOP_CRY ) { */
7217 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7218 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7219 /* pic16_outBitC(result); */
7221 /* tlbl = newiTempLabel(NULL); */
7222 /* pic16_toBoolean(left); */
7223 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7224 /* pic16_toBoolean(right); */
7225 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7226 /* pic16_outBitAcc(result); */
7229 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7230 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7231 pic16_freeAsmop(result,NULL,ic,TRUE);
7235 /*-----------------------------------------------------------------*/
7236 /* genOrOp - for || operation */
7237 /*-----------------------------------------------------------------*/
7240 modified this code, but it doesn't appear to ever get called
7243 static void genOrOp (iCode *ic)
7245 operand *left,*right, *result;
7250 /* note here that || operations that are in an
7251 if statement are taken away by backPatchLabels
7252 only those used in arthmetic operations remain */
7253 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7254 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7255 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7257 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7259 /* if both are bit variables */
7260 if (AOP_TYPE(left) == AOP_CRY &&
7261 AOP_TYPE(right) == AOP_CRY ) {
7262 pic16_emitcode("clrc","");
7263 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7264 AOP(left)->aopu.aop_dir,
7265 AOP(left)->aopu.aop_dir);
7266 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7267 AOP(right)->aopu.aop_dir,
7268 AOP(right)->aopu.aop_dir);
7269 pic16_emitcode("setc","");
7272 tlbl = newiTempLabel(NULL);
7273 pic16_toBoolean(left);
7275 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7276 pic16_toBoolean(right);
7277 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7279 pic16_outBitAcc(result);
7282 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7283 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7284 pic16_freeAsmop(result,NULL,ic,TRUE);
7287 /*-----------------------------------------------------------------*/
7288 /* isLiteralBit - test if lit == 2^n */
7289 /*-----------------------------------------------------------------*/
7290 static int isLiteralBit(unsigned long lit)
7292 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7293 0x100L,0x200L,0x400L,0x800L,
7294 0x1000L,0x2000L,0x4000L,0x8000L,
7295 0x10000L,0x20000L,0x40000L,0x80000L,
7296 0x100000L,0x200000L,0x400000L,0x800000L,
7297 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7298 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7301 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7302 for(idx = 0; idx < 32; idx++)
7308 /*-----------------------------------------------------------------*/
7309 /* continueIfTrue - */
7310 /*-----------------------------------------------------------------*/
7311 static void continueIfTrue (iCode *ic)
7315 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7319 /*-----------------------------------------------------------------*/
7321 /*-----------------------------------------------------------------*/
7322 static void jumpIfTrue (iCode *ic)
7326 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7330 /*-----------------------------------------------------------------*/
7331 /* jmpTrueOrFalse - */
7332 /*-----------------------------------------------------------------*/
7333 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7335 // ugly but optimized by peephole
7338 symbol *nlbl = newiTempLabel(NULL);
7339 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7340 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7341 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7342 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7344 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7345 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7350 /*-----------------------------------------------------------------*/
7351 /* genAnd - code for and */
7352 /*-----------------------------------------------------------------*/
7353 static void genAnd (iCode *ic, iCode *ifx)
7355 operand *left, *right, *result;
7357 unsigned long lit = 0L;
7363 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7364 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7365 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7367 resolveIfx(&rIfx,ifx);
7369 /* if left is a literal & right is not then exchange them */
7370 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7371 AOP_NEEDSACC(left)) {
7372 operand *tmp = right ;
7377 /* if result = right then exchange them */
7378 if(pic16_sameRegs(AOP(result),AOP(right))){
7379 operand *tmp = right ;
7384 /* if right is bit then exchange them */
7385 if (AOP_TYPE(right) == AOP_CRY &&
7386 AOP_TYPE(left) != AOP_CRY){
7387 operand *tmp = right ;
7391 if(AOP_TYPE(right) == AOP_LIT)
7392 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7394 size = AOP_SIZE(result);
7396 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7399 // result = bit & yy;
7400 if (AOP_TYPE(left) == AOP_CRY){
7401 // c = bit & literal;
7402 if(AOP_TYPE(right) == AOP_LIT){
7404 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7407 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7410 if(size && (AOP_TYPE(result) == AOP_CRY)){
7411 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7414 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7418 pic16_emitcode("clr","c");
7421 if (AOP_TYPE(right) == AOP_CRY){
7423 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7424 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7427 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7429 pic16_emitcode("rrc","a");
7430 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7436 pic16_outBitC(result);
7438 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7439 genIfxJump(ifx, "c");
7443 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7444 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7445 if((AOP_TYPE(right) == AOP_LIT) &&
7446 (AOP_TYPE(result) == AOP_CRY) &&
7447 (AOP_TYPE(left) != AOP_CRY)){
7448 int posbit = isLiteralBit(lit);
7452 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7455 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7461 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7462 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7464 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7465 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7468 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7469 size = AOP_SIZE(left);
7472 int bp = posbit, ofs=0;
7479 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7480 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7484 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7485 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7487 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7494 symbol *tlbl = newiTempLabel(NULL);
7495 int sizel = AOP_SIZE(left);
7501 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7503 /* patch provided by Aaron Colwell */
7504 if((posbit = isLiteralBit(bytelit)) != 0) {
7505 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7506 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7507 (posbit-1),0, PO_GPR_REGISTER));
7509 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7510 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7512 if (bytelit == 0xff) {
7513 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7514 * a peephole could optimize it out -- VR */
7515 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7517 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7518 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7521 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7522 pic16_popGetLabel(tlbl->key));
7526 /* old code, left here for reference -- VR 09/2004 */
7527 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7529 if((posbit = isLiteralBit(bytelit)) != 0)
7530 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7532 if(bytelit != 0x0FFL)
7533 pic16_emitcode("anl","a,%s",
7534 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7535 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7541 // bit = left & literal
7544 pic16_emitpLabel(tlbl->key);
7546 // if(left & literal)
7549 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7552 pic16_emitpLabel(tlbl->key);
7557 pic16_outBitC(result);
7561 /* if left is same as result */
7562 if(pic16_sameRegs(AOP(result),AOP(left))){
7564 for(;size--; offset++,lit>>=8) {
7565 if(AOP_TYPE(right) == AOP_LIT){
7566 switch(lit & 0xff) {
7568 /* and'ing with 0 has clears the result */
7569 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7570 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7573 /* and'ing with 0xff is a nop when the result and left are the same */
7578 int p = pic16_my_powof2( (~lit) & 0xff );
7580 /* only one bit is set in the literal, so use a bcf instruction */
7581 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7582 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7585 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7586 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7587 if(know_W != (lit&0xff))
7588 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7590 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7595 if (AOP_TYPE(left) == AOP_ACC) {
7596 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7598 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7599 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7606 // left & result in different registers
7607 if(AOP_TYPE(result) == AOP_CRY){
7609 // if(size), result in bit
7610 // if(!size && ifx), conditional oper: if(left & right)
7611 symbol *tlbl = newiTempLabel(NULL);
7612 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7614 pic16_emitcode("setb","c");
7616 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7617 pic16_emitcode("anl","a,%s",
7618 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7619 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7624 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7625 pic16_outBitC(result);
7627 jmpTrueOrFalse(ifx, tlbl);
7629 for(;(size--);offset++) {
7631 // result = left & right
7632 if(AOP_TYPE(right) == AOP_LIT){
7633 int t = (lit >> (offset*8)) & 0x0FFL;
7636 pic16_emitcode("clrf","%s",
7637 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7638 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7641 pic16_emitcode("movf","%s,w",
7642 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7643 pic16_emitcode("movwf","%s",
7644 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7645 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7646 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7649 pic16_emitcode("movlw","0x%x",t);
7650 pic16_emitcode("andwf","%s,w",
7651 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7652 pic16_emitcode("movwf","%s",
7653 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7655 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7656 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7657 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7662 if (AOP_TYPE(left) == AOP_ACC) {
7663 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7664 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7666 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7667 pic16_emitcode("andwf","%s,w",
7668 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7669 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7670 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7672 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7673 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7679 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7680 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7681 pic16_freeAsmop(result,NULL,ic,TRUE);
7684 /*-----------------------------------------------------------------*/
7685 /* genOr - code for or */
7686 /*-----------------------------------------------------------------*/
7687 static void genOr (iCode *ic, iCode *ifx)
7689 operand *left, *right, *result;
7691 unsigned long lit = 0L;
7693 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7695 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7696 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7697 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7699 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7701 /* if left is a literal & right is not then exchange them */
7702 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7703 AOP_NEEDSACC(left)) {
7704 operand *tmp = right ;
7709 /* if result = right then exchange them */
7710 if(pic16_sameRegs(AOP(result),AOP(right))){
7711 operand *tmp = right ;
7716 /* if right is bit then exchange them */
7717 if (AOP_TYPE(right) == AOP_CRY &&
7718 AOP_TYPE(left) != AOP_CRY){
7719 operand *tmp = right ;
7724 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7726 if(AOP_TYPE(right) == AOP_LIT)
7727 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7729 size = AOP_SIZE(result);
7733 if (AOP_TYPE(left) == AOP_CRY){
7734 if(AOP_TYPE(right) == AOP_LIT){
7735 // c = bit & literal;
7737 // lit != 0 => result = 1
7738 if(AOP_TYPE(result) == AOP_CRY){
7740 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7741 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7742 // AOP(result)->aopu.aop_dir,
7743 // AOP(result)->aopu.aop_dir);
7745 continueIfTrue(ifx);
7749 // lit == 0 => result = left
7750 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7752 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7755 if (AOP_TYPE(right) == AOP_CRY){
7756 if(pic16_sameRegs(AOP(result),AOP(left))){
7758 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7759 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7760 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7762 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7763 AOP(result)->aopu.aop_dir,
7764 AOP(result)->aopu.aop_dir);
7765 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7766 AOP(right)->aopu.aop_dir,
7767 AOP(right)->aopu.aop_dir);
7768 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7769 AOP(result)->aopu.aop_dir,
7770 AOP(result)->aopu.aop_dir);
7772 if( AOP_TYPE(result) == AOP_ACC) {
7773 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7774 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7775 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7776 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7780 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7781 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7782 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7783 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7785 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7786 AOP(result)->aopu.aop_dir,
7787 AOP(result)->aopu.aop_dir);
7788 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7789 AOP(right)->aopu.aop_dir,
7790 AOP(right)->aopu.aop_dir);
7791 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7792 AOP(left)->aopu.aop_dir,
7793 AOP(left)->aopu.aop_dir);
7794 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7795 AOP(result)->aopu.aop_dir,
7796 AOP(result)->aopu.aop_dir);
7801 symbol *tlbl = newiTempLabel(NULL);
7802 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7805 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7806 if( AOP_TYPE(right) == AOP_ACC) {
7807 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7809 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7810 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7815 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7816 pic16_emitcode(";XXX setb","c");
7817 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7818 AOP(left)->aopu.aop_dir,tlbl->key+100);
7819 pic16_toBoolean(right);
7820 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7821 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7822 jmpTrueOrFalse(ifx, tlbl);
7826 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7833 pic16_outBitC(result);
7835 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7836 genIfxJump(ifx, "c");
7840 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7841 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7842 if((AOP_TYPE(right) == AOP_LIT) &&
7843 (AOP_TYPE(result) == AOP_CRY) &&
7844 (AOP_TYPE(left) != AOP_CRY)){
7846 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7849 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7851 continueIfTrue(ifx);
7854 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7855 // lit = 0, result = boolean(left)
7857 pic16_emitcode(";XXX setb","c");
7858 pic16_toBoolean(right);
7860 symbol *tlbl = newiTempLabel(NULL);
7861 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7863 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7865 genIfxJump (ifx,"a");
7869 pic16_outBitC(result);
7873 /* if left is same as result */
7874 if(pic16_sameRegs(AOP(result),AOP(left))){
7876 for(;size--; offset++,lit>>=8) {
7877 if(AOP_TYPE(right) == AOP_LIT){
7878 if((lit & 0xff) == 0)
7879 /* or'ing with 0 has no effect */
7882 int p = pic16_my_powof2(lit & 0xff);
7884 /* only one bit is set in the literal, so use a bsf instruction */
7885 pic16_emitpcode(POC_BSF,
7886 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7888 if(know_W != (lit & 0xff))
7889 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7890 know_W = lit & 0xff;
7891 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7896 if (AOP_TYPE(left) == AOP_ACC) {
7897 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7898 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7900 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7901 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7903 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7904 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7910 // left & result in different registers
7911 if(AOP_TYPE(result) == AOP_CRY){
7913 // if(size), result in bit
7914 // if(!size && ifx), conditional oper: if(left | right)
7915 symbol *tlbl = newiTempLabel(NULL);
7916 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7917 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7921 pic16_emitcode(";XXX setb","c");
7923 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7924 pic16_emitcode(";XXX orl","a,%s",
7925 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7926 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7931 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7932 pic16_outBitC(result);
7934 jmpTrueOrFalse(ifx, tlbl);
7935 } else for(;(size--);offset++){
7937 // result = left & right
7938 if(AOP_TYPE(right) == AOP_LIT){
7939 int t = (lit >> (offset*8)) & 0x0FFL;
7942 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7943 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7945 pic16_emitcode("movf","%s,w",
7946 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7947 pic16_emitcode("movwf","%s",
7948 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7951 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7952 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7953 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7955 pic16_emitcode("movlw","0x%x",t);
7956 pic16_emitcode("iorwf","%s,w",
7957 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7958 pic16_emitcode("movwf","%s",
7959 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7965 // faster than result <- left, anl result,right
7966 // and better if result is SFR
7967 if (AOP_TYPE(left) == AOP_ACC) {
7968 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7969 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7971 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7972 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7974 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7975 pic16_emitcode("iorwf","%s,w",
7976 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7978 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7979 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7984 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7985 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7986 pic16_freeAsmop(result,NULL,ic,TRUE);
7989 /*-----------------------------------------------------------------*/
7990 /* genXor - code for xclusive or */
7991 /*-----------------------------------------------------------------*/
7992 static void genXor (iCode *ic, iCode *ifx)
7994 operand *left, *right, *result;
7996 unsigned long lit = 0L;
7998 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8000 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8001 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8002 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8004 /* if left is a literal & right is not ||
8005 if left needs acc & right does not */
8006 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8007 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8008 operand *tmp = right ;
8013 /* if result = right then exchange them */
8014 if(pic16_sameRegs(AOP(result),AOP(right))){
8015 operand *tmp = right ;
8020 /* if right is bit then exchange them */
8021 if (AOP_TYPE(right) == AOP_CRY &&
8022 AOP_TYPE(left) != AOP_CRY){
8023 operand *tmp = right ;
8027 if(AOP_TYPE(right) == AOP_LIT)
8028 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8030 size = AOP_SIZE(result);
8034 if (AOP_TYPE(left) == AOP_CRY){
8035 if(AOP_TYPE(right) == AOP_LIT){
8036 // c = bit & literal;
8038 // lit>>1 != 0 => result = 1
8039 if(AOP_TYPE(result) == AOP_CRY){
8041 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8042 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8044 continueIfTrue(ifx);
8047 pic16_emitcode("setb","c");
8051 // lit == 0, result = left
8052 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8054 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8056 // lit == 1, result = not(left)
8057 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8058 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8059 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8060 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8063 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8064 pic16_emitcode("cpl","c");
8071 symbol *tlbl = newiTempLabel(NULL);
8072 if (AOP_TYPE(right) == AOP_CRY){
8074 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8077 int sizer = AOP_SIZE(right);
8079 // if val>>1 != 0, result = 1
8080 pic16_emitcode("setb","c");
8082 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8084 // test the msb of the lsb
8085 pic16_emitcode("anl","a,#0xfe");
8086 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8090 pic16_emitcode("rrc","a");
8092 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8093 pic16_emitcode("cpl","c");
8094 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8099 pic16_outBitC(result);
8101 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8102 genIfxJump(ifx, "c");
8106 if(pic16_sameRegs(AOP(result),AOP(left))){
8107 /* if left is same as result */
8108 for(;size--; offset++) {
8109 if(AOP_TYPE(right) == AOP_LIT){
8110 int t = (lit >> (offset*8)) & 0x0FFL;
8114 if (IS_AOP_PREG(left)) {
8115 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8116 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8117 pic16_aopPut(AOP(result),"a",offset);
8119 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8120 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8121 pic16_emitcode("xrl","%s,%s",
8122 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8123 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8126 if (AOP_TYPE(left) == AOP_ACC)
8127 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8129 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8130 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8132 if (IS_AOP_PREG(left)) {
8133 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8134 pic16_aopPut(AOP(result),"a",offset);
8136 pic16_emitcode("xrl","%s,a",
8137 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8143 // left & result in different registers
8144 if(AOP_TYPE(result) == AOP_CRY){
8146 // if(size), result in bit
8147 // if(!size && ifx), conditional oper: if(left ^ right)
8148 symbol *tlbl = newiTempLabel(NULL);
8149 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8151 pic16_emitcode("setb","c");
8153 if((AOP_TYPE(right) == AOP_LIT) &&
8154 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8155 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8157 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8158 pic16_emitcode("xrl","a,%s",
8159 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8161 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8166 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8167 pic16_outBitC(result);
8169 jmpTrueOrFalse(ifx, tlbl);
8170 } else for(;(size--);offset++){
8172 // result = left & right
8173 if(AOP_TYPE(right) == AOP_LIT){
8174 int t = (lit >> (offset*8)) & 0x0FFL;
8177 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8178 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8179 pic16_emitcode("movf","%s,w",
8180 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8181 pic16_emitcode("movwf","%s",
8182 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8185 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8186 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8187 pic16_emitcode("comf","%s,w",
8188 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8189 pic16_emitcode("movwf","%s",
8190 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8193 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8194 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8195 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8196 pic16_emitcode("movlw","0x%x",t);
8197 pic16_emitcode("xorwf","%s,w",
8198 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8199 pic16_emitcode("movwf","%s",
8200 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8206 // faster than result <- left, anl result,right
8207 // and better if result is SFR
8208 if (AOP_TYPE(left) == AOP_ACC) {
8209 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8210 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8212 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8213 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8214 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8215 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8217 if ( AOP_TYPE(result) != AOP_ACC){
8218 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8219 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8225 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8226 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8227 pic16_freeAsmop(result,NULL,ic,TRUE);
8230 /*-----------------------------------------------------------------*/
8231 /* genInline - write the inline code out */
8232 /*-----------------------------------------------------------------*/
8233 static void genInline (iCode *ic)
8235 char *buffer, *bp, *bp1;
8237 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8239 _G.inLine += (!options.asmpeep);
8241 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8242 strcpy(buffer,IC_INLINE(ic));
8244 while((bp1=strstr(bp, "\\n"))) {
8252 /* This is an experimental code for #pragma inline
8253 and is temporarily disabled for 2.5.0 release */
8261 cbuf = Safe_strdup(buffer);
8262 cblen = strlen(buffer)+1;
8263 memset(cbuf, 0, cblen);
8268 if(*bp != '%')*bp1++ = *bp++;
8274 if(i>elementsInSet(asmInlineMap))break;
8277 s = indexSet(asmInlineMap, i);
8278 DEBUGpc("searching symbol s = `%s'", s);
8279 sym = findSym(SymbolTab, NULL, s);
8282 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8284 strcat(bp1, sym->rname);
8290 if(strlen(bp1) > cblen - 16) {
8291 int i = strlen(cbuf);
8293 cbuf = realloc(cbuf, cblen);
8294 memset(cbuf+i, 0, 50);
8300 buffer = Safe_strdup( cbuf );
8307 /* emit each line as a code */
8313 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8321 /* print label, use this special format with NULL directive
8322 * to denote that the argument should not be indented with tab */
8323 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8330 if ((bp1 != bp) && *bp1)
8331 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8336 _G.inLine -= (!options.asmpeep);
8339 /*-----------------------------------------------------------------*/
8340 /* genRRC - rotate right with carry */
8341 /*-----------------------------------------------------------------*/
8342 static void genRRC (iCode *ic)
8344 operand *left , *result ;
8345 int size, offset = 0, same;
8347 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8349 /* rotate right with carry */
8351 result=IC_RESULT(ic);
8352 pic16_aopOp (left,ic,FALSE);
8353 pic16_aopOp (result,ic,TRUE);
8355 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8357 same = pic16_sameRegs(AOP(result),AOP(left));
8359 size = AOP_SIZE(result);
8361 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8363 /* get the lsb and put it into the carry */
8364 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8371 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8373 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8374 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8380 pic16_freeAsmop(left,NULL,ic,TRUE);
8381 pic16_freeAsmop(result,NULL,ic,TRUE);
8384 /*-----------------------------------------------------------------*/
8385 /* genRLC - generate code for rotate left with carry */
8386 /*-----------------------------------------------------------------*/
8387 static void genRLC (iCode *ic)
8389 operand *left , *result ;
8390 int size, offset = 0;
8393 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8394 /* rotate right with carry */
8396 result=IC_RESULT(ic);
8397 pic16_aopOp (left,ic,FALSE);
8398 pic16_aopOp (result,ic,TRUE);
8400 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8402 same = pic16_sameRegs(AOP(result),AOP(left));
8404 /* move it to the result */
8405 size = AOP_SIZE(result);
8407 /* get the msb and put it into the carry */
8408 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8415 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8417 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8418 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8425 pic16_freeAsmop(left,NULL,ic,TRUE);
8426 pic16_freeAsmop(result,NULL,ic,TRUE);
8430 /* gpasm can get the highest order bit with HIGH/UPPER
8431 * so the following probably is not needed -- VR */
8433 /*-----------------------------------------------------------------*/
8434 /* genGetHbit - generates code get highest order bit */
8435 /*-----------------------------------------------------------------*/
8436 static void genGetHbit (iCode *ic)
8438 operand *left, *result;
8440 result=IC_RESULT(ic);
8441 pic16_aopOp (left,ic,FALSE);
8442 pic16_aopOp (result,ic,FALSE);
8444 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8445 /* get the highest order byte into a */
8446 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8447 if(AOP_TYPE(result) == AOP_CRY){
8448 pic16_emitcode("rlc","a");
8449 pic16_outBitC(result);
8452 pic16_emitcode("rl","a");
8453 pic16_emitcode("anl","a,#0x01");
8454 pic16_outAcc(result);
8458 pic16_freeAsmop(left,NULL,ic,TRUE);
8459 pic16_freeAsmop(result,NULL,ic,TRUE);
8463 /*-----------------------------------------------------------------*/
8464 /* AccRol - rotate left accumulator by known count */
8465 /*-----------------------------------------------------------------*/
8466 static void AccRol (int shCount)
8468 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8469 shCount &= 0x0007; // shCount : 0..7
8474 pic16_emitcode("rl","a");
8477 pic16_emitcode("rl","a");
8478 pic16_emitcode("rl","a");
8481 pic16_emitcode("swap","a");
8482 pic16_emitcode("rr","a");
8485 pic16_emitcode("swap","a");
8488 pic16_emitcode("swap","a");
8489 pic16_emitcode("rl","a");
8492 pic16_emitcode("rr","a");
8493 pic16_emitcode("rr","a");
8496 pic16_emitcode("rr","a");
8502 /*-----------------------------------------------------------------*/
8503 /* AccLsh - left shift accumulator by known count */
8504 /*-----------------------------------------------------------------*/
8505 static void AccLsh (int shCount)
8507 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8513 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8516 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8517 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8520 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8521 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8524 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8527 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8528 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8531 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8532 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8535 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8539 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8542 /*-----------------------------------------------------------------*/
8543 /* AccRsh - right shift accumulator by known count */
8544 /*-----------------------------------------------------------------*/
8545 static void AccRsh (int shCount, int andmask)
8547 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8552 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8555 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8556 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8559 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8560 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8563 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8566 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8567 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8570 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8571 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8574 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8579 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8581 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8585 /*-----------------------------------------------------------------*/
8586 /* AccSRsh - signed right shift accumulator by known count */
8587 /*-----------------------------------------------------------------*/
8588 static void AccSRsh (int shCount)
8591 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8594 pic16_emitcode("mov","c,acc.7");
8595 pic16_emitcode("rrc","a");
8596 } else if(shCount == 2){
8597 pic16_emitcode("mov","c,acc.7");
8598 pic16_emitcode("rrc","a");
8599 pic16_emitcode("mov","c,acc.7");
8600 pic16_emitcode("rrc","a");
8602 tlbl = newiTempLabel(NULL);
8603 /* rotate right accumulator */
8604 AccRol(8 - shCount);
8605 /* and kill the higher order bits */
8606 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8607 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8608 pic16_emitcode("orl","a,#0x%02x",
8609 (unsigned char)~SRMask[shCount]);
8610 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8616 /*-----------------------------------------------------------------*/
8617 /* shiftR1Left2Result - shift right one byte from left to result */
8618 /*-----------------------------------------------------------------*/
8619 static void shiftR1Left2ResultSigned (operand *left, int offl,
8620 operand *result, int offr,
8625 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8627 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8631 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8633 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8635 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8636 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8642 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8644 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8646 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8647 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8649 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8650 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8656 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8658 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8659 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8662 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8663 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8664 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8666 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8667 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8669 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8673 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8674 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8675 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8676 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8677 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8681 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8683 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8684 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8686 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8687 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8688 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8689 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8690 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8695 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8696 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8697 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8698 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8699 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8700 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8702 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8703 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8704 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8705 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8706 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8712 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8713 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8714 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8715 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8717 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8718 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8719 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8727 /*-----------------------------------------------------------------*/
8728 /* shiftR1Left2Result - shift right one byte from left to result */
8729 /*-----------------------------------------------------------------*/
8730 static void shiftR1Left2Result (operand *left, int offl,
8731 operand *result, int offr,
8732 int shCount, int sign)
8736 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8738 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8740 /* Copy the msb into the carry if signed. */
8742 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8752 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8754 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8755 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8761 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8763 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8764 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8767 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8772 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8774 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8775 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8778 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8779 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8780 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8781 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8785 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8786 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8787 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8791 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8792 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8793 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8795 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8800 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8801 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8802 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8803 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8804 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8809 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8810 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8811 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8820 /*-----------------------------------------------------------------*/
8821 /* shiftL1Left2Result - shift left one byte from left to result */
8822 /*-----------------------------------------------------------------*/
8823 static void shiftL1Left2Result (operand *left, int offl,
8824 operand *result, int offr, int shCount)
8829 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8831 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8832 DEBUGpic16_emitcode ("; ***","same = %d",same);
8833 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8835 /* shift left accumulator */
8836 //AccLsh(shCount); // don't comment out just yet...
8837 // pic16_aopPut(AOP(result),"a",offr);
8841 /* Shift left 1 bit position */
8842 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8844 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8846 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8847 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8851 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8852 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8853 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8854 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8857 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8858 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8859 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8860 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8861 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8864 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8865 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8866 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8869 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8870 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8871 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8872 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8875 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8876 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8877 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8878 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8879 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8882 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8883 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8884 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8888 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8893 /*-----------------------------------------------------------------*/
8894 /* movLeft2Result - move byte from left to result */
8895 /*-----------------------------------------------------------------*/
8896 static void movLeft2Result (operand *left, int offl,
8897 operand *result, int offr)
8900 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8901 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8902 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8904 if (*l == '@' && (IS_AOP_PREG(result))) {
8905 pic16_emitcode("mov","a,%s",l);
8906 pic16_aopPut(AOP(result),"a",offr);
8908 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8909 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8914 /*-----------------------------------------------------------------*/
8915 /* shiftL2Left2Result - shift left two bytes from left to result */
8916 /*-----------------------------------------------------------------*/
8917 static void shiftL2Left2Result (operand *left, int offl,
8918 operand *result, int offr, int shCount)
8920 int same = pic16_sameRegs(AOP(result), AOP(left));
8923 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8925 if (same && (offl != offr)) { // shift bytes
8928 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8929 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8931 } else { // just treat as different later on
8944 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8945 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8946 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8950 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8951 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8957 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8958 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8959 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8960 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8961 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8962 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8963 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8965 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8966 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8970 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8971 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8972 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8973 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8974 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8975 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8976 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8977 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8978 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8979 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8982 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8983 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8984 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8985 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8986 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8996 /* note, use a mov/add for the shift since the mov has a
8997 chance of getting optimized out */
8998 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8999 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9000 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9001 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9002 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9006 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9007 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9013 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9014 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9015 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9016 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9017 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9018 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9019 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9020 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9024 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9025 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9029 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9030 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9031 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9032 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9034 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9035 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9036 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9037 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9038 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9039 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9040 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9041 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9044 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9045 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9046 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9047 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9048 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9053 /*-----------------------------------------------------------------*/
9054 /* shiftR2Left2Result - shift right two bytes from left to result */
9055 /*-----------------------------------------------------------------*/
9056 static void shiftR2Left2Result (operand *left, int offl,
9057 operand *result, int offr,
9058 int shCount, int sign)
9060 int same = pic16_sameRegs(AOP(result), AOP(left));
9062 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9064 if (same && (offl != offr)) { // shift right bytes
9067 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9068 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9070 } else { // just treat as different later on
9082 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9087 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9088 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9090 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9091 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9092 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9093 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9098 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9101 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9102 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9109 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9110 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9111 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9113 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9114 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9115 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9116 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9118 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9119 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9120 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9122 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9123 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9124 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9125 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9126 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9130 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9131 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9135 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9136 pic16_emitpcode(POC_BTFSC,
9137 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9138 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9146 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9147 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9149 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9150 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9151 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9152 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9154 pic16_emitpcode(POC_BTFSC,
9155 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9156 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9158 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9159 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9160 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9161 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9163 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9164 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9165 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9166 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9167 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9168 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9169 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9170 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9172 pic16_emitpcode(POC_BTFSC,
9173 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9174 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9176 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9177 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9184 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9185 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9186 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9187 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9190 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9192 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9197 /*-----------------------------------------------------------------*/
9198 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9199 /*-----------------------------------------------------------------*/
9200 static void shiftLLeftOrResult (operand *left, int offl,
9201 operand *result, int offr, int shCount)
9203 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9205 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9206 /* shift left accumulator */
9208 /* or with result */
9209 /* back to result */
9210 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9213 /*-----------------------------------------------------------------*/
9214 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9215 /*-----------------------------------------------------------------*/
9216 static void shiftRLeftOrResult (operand *left, int offl,
9217 operand *result, int offr, int shCount)
9219 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9221 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9222 /* shift right accumulator */
9224 /* or with result */
9225 /* back to result */
9226 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9229 /*-----------------------------------------------------------------*/
9230 /* genlshOne - left shift a one byte quantity by known count */
9231 /*-----------------------------------------------------------------*/
9232 static void genlshOne (operand *result, operand *left, int shCount)
9234 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9235 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9238 /*-----------------------------------------------------------------*/
9239 /* genlshTwo - left shift two bytes by known amount != 0 */
9240 /*-----------------------------------------------------------------*/
9241 static void genlshTwo (operand *result,operand *left, int shCount)
9245 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9246 size = pic16_getDataSize(result);
9248 /* if shCount >= 8 */
9254 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9256 movLeft2Result(left, LSB, result, MSB16);
9258 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9261 /* 1 <= shCount <= 7 */
9264 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9266 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9270 /*-----------------------------------------------------------------*/
9271 /* shiftLLong - shift left one long from left to result */
9272 /* offr = LSB or MSB16 */
9273 /*-----------------------------------------------------------------*/
9274 static void shiftLLong (operand *left, operand *result, int offr )
9276 int size = AOP_SIZE(result);
9277 int same = pic16_sameRegs(AOP(left),AOP(result));
9280 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9282 if (same && (offr == MSB16)) { //shift one byte
9283 for(i=size-1;i>=MSB16;i--) {
9284 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9285 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9288 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9291 if (size > LSB+offr ){
9293 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9295 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9296 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9300 if(size > MSB16+offr){
9302 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9304 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9305 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9309 if(size > MSB24+offr){
9311 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9313 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9314 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9318 if(size > MSB32+offr){
9320 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9322 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9323 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9327 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9331 /*-----------------------------------------------------------------*/
9332 /* genlshFour - shift four byte by a known amount != 0 */
9333 /*-----------------------------------------------------------------*/
9334 static void genlshFour (operand *result, operand *left, int shCount)
9338 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9339 size = AOP_SIZE(result);
9341 /* if shifting more that 3 bytes */
9342 if (shCount >= 24 ) {
9345 /* lowest order of left goes to the highest
9346 order of the destination */
9347 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9349 movLeft2Result(left, LSB, result, MSB32);
9351 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9352 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9353 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9358 /* more than two bytes */
9359 else if ( shCount >= 16 ) {
9360 /* lower order two bytes goes to higher order two bytes */
9362 /* if some more remaining */
9364 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9366 movLeft2Result(left, MSB16, result, MSB32);
9367 movLeft2Result(left, LSB, result, MSB24);
9369 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9370 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9374 /* if more than 1 byte */
9375 else if ( shCount >= 8 ) {
9376 /* lower order three bytes goes to higher order three bytes */
9380 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9382 movLeft2Result(left, LSB, result, MSB16);
9384 else{ /* size = 4 */
9386 movLeft2Result(left, MSB24, result, MSB32);
9387 movLeft2Result(left, MSB16, result, MSB24);
9388 movLeft2Result(left, LSB, result, MSB16);
9389 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9391 else if(shCount == 1)
9392 shiftLLong(left, result, MSB16);
9394 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9395 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9396 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9397 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9402 /* 1 <= shCount <= 7 */
9403 else if(shCount <= 3)
9405 shiftLLong(left, result, LSB);
9406 while(--shCount >= 1)
9407 shiftLLong(result, result, LSB);
9409 /* 3 <= shCount <= 7, optimize */
9411 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9412 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9413 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9417 /*-----------------------------------------------------------------*/
9418 /* genLeftShiftLiteral - left shifting by known count */
9419 /*-----------------------------------------------------------------*/
9420 void pic16_genLeftShiftLiteral (operand *left,
9425 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9429 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9430 pic16_freeAsmop(right,NULL,ic,TRUE);
9432 pic16_aopOp(left,ic,FALSE);
9433 pic16_aopOp(result,ic,TRUE);
9435 size = getSize(operandType(result));
9438 pic16_emitcode("; shift left ","result %d, left %d",size,
9442 /* I suppose that the left size >= result size */
9445 movLeft2Result(left, size, result, size);
9449 else if(shCount >= (size * 8))
9451 pic16_aopPut(AOP(result),zero,size);
9455 genlshOne (result,left,shCount);
9460 genlshTwo (result,left,shCount);
9464 genlshFour (result,left,shCount);
9468 pic16_freeAsmop(left,NULL,ic,TRUE);
9469 pic16_freeAsmop(result,NULL,ic,TRUE);
9472 /*-----------------------------------------------------------------*
9473 * genMultiAsm - repeat assembly instruction for size of register.
9474 * if endian == 1, then the high byte (i.e base address + size of
9475 * register) is used first else the low byte is used first;
9476 *-----------------------------------------------------------------*/
9477 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9482 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9495 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9501 #if !(USE_GENERIC_SIGNED_SHIFT)
9502 /*-----------------------------------------------------------------*/
9503 /* genLeftShift - generates code for left shifting */
9504 /*-----------------------------------------------------------------*/
9505 static void genLeftShift (iCode *ic)
9507 operand *left,*right, *result;
9510 symbol *tlbl , *tlbl1;
9513 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9515 right = IC_RIGHT(ic);
9517 result = IC_RESULT(ic);
9519 pic16_aopOp(right,ic,FALSE);
9521 /* if the shift count is known then do it
9522 as efficiently as possible */
9523 if (AOP_TYPE(right) == AOP_LIT) {
9524 pic16_genLeftShiftLiteral (left,right,result,ic);
9528 /* shift count is unknown then we have to form
9529 * a loop. Get the loop count in WREG : Note: we take
9530 * only the lower order byte since shifting
9531 * more than 32 bits make no sense anyway, ( the
9532 * largest size of an object can be only 32 bits ) */
9534 pic16_aopOp(left,ic,FALSE);
9535 pic16_aopOp(result,ic,FALSE);
9537 /* now move the left to the result if they are not the
9538 * same, and if size > 1,
9539 * and if right is not same to result (!!!) -- VR */
9540 if (!pic16_sameRegs(AOP(left),AOP(result))
9541 && (AOP_SIZE(result) > 1)) {
9543 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9545 size = AOP_SIZE(result);
9550 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9551 if (*l == '@' && (IS_AOP_PREG(result))) {
9553 pic16_emitcode("mov","a,%s",l);
9554 pic16_aopPut(AOP(result),"a",offset);
9558 /* we don't know if left is a literal or a register, take care -- VR */
9559 pic16_mov2f(AOP(result), AOP(left), offset);
9565 size = AOP_SIZE(result);
9567 /* if it is only one byte then */
9569 if(optimized_for_speed) {
9570 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9571 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9572 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9573 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9574 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9575 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9576 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9577 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9578 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9579 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9580 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9581 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9584 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9586 tlbl = newiTempLabel(NULL);
9589 /* this is already done, why change it? */
9590 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9591 pic16_mov2f(AOP(result), AOP(left), 0);
9595 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9596 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9597 pic16_emitpLabel(tlbl->key);
9598 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9599 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9601 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9606 if (pic16_sameRegs(AOP(left),AOP(result))) {
9608 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9610 tlbl = newiTempLabel(NULL);
9611 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9612 genMultiAsm(POC_RRCF, result, size,1);
9613 pic16_emitpLabel(tlbl->key);
9614 genMultiAsm(POC_RLCF, result, size,0);
9615 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9617 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9621 //tlbl = newiTempLabel(NULL);
9623 //tlbl1 = newiTempLabel(NULL);
9625 //reAdjustPreg(AOP(result));
9627 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9628 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9629 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9631 //pic16_emitcode("add","a,acc");
9632 //pic16_aopPut(AOP(result),"a",offset++);
9634 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9636 // pic16_emitcode("rlc","a");
9637 // pic16_aopPut(AOP(result),"a",offset++);
9639 //reAdjustPreg(AOP(result));
9641 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9642 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9645 tlbl = newiTempLabel(NULL);
9646 tlbl1= newiTempLabel(NULL);
9648 size = AOP_SIZE(result);
9651 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9653 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9655 /* offset should be 0, 1 or 3 */
9657 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9659 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9661 pic16_emitpcode(POC_MOVWF, pctemp);
9664 pic16_emitpLabel(tlbl->key);
9667 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9669 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9671 pic16_emitpcode(POC_DECFSZ, pctemp);
9672 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9673 pic16_emitpLabel(tlbl1->key);
9675 pic16_popReleaseTempReg(pctemp,1);
9679 pic16_freeAsmop (right,NULL,ic,TRUE);
9680 pic16_freeAsmop(left,NULL,ic,TRUE);
9681 pic16_freeAsmop(result,NULL,ic,TRUE);
9687 #error old code (left here for reference)
9688 /*-----------------------------------------------------------------*/
9689 /* genLeftShift - generates code for left shifting */
9690 /*-----------------------------------------------------------------*/
9691 static void genLeftShift (iCode *ic)
9693 operand *left,*right, *result;
9696 symbol *tlbl , *tlbl1;
9699 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9701 right = IC_RIGHT(ic);
9703 result = IC_RESULT(ic);
9705 pic16_aopOp(right,ic,FALSE);
9707 /* if the shift count is known then do it
9708 as efficiently as possible */
9709 if (AOP_TYPE(right) == AOP_LIT) {
9710 pic16_genLeftShiftLiteral (left,right,result,ic);
9714 /* shift count is unknown then we have to form
9715 a loop get the loop count in B : Note: we take
9716 only the lower order byte since shifting
9717 more that 32 bits make no sense anyway, ( the
9718 largest size of an object can be only 32 bits ) */
9721 pic16_aopOp(left,ic,FALSE);
9722 pic16_aopOp(result,ic,FALSE);
9724 /* now move the left to the result if they are not the
9726 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9727 AOP_SIZE(result) > 1) {
9729 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9731 size = AOP_SIZE(result);
9734 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9735 if (*l == '@' && (IS_AOP_PREG(result))) {
9737 pic16_emitcode("mov","a,%s",l);
9738 pic16_aopPut(AOP(result),"a",offset);
9741 /* we don't know if left is a literal or a register, take care -- VR */
9742 pic16_mov2f(AOP(result), AOP(left), offset);
9748 size = AOP_SIZE(result);
9750 /* if it is only one byte then */
9752 if(optimized_for_speed) {
9753 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9754 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9755 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9756 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9757 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9758 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9759 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9760 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9761 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9762 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9763 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9764 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9767 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9769 tlbl = newiTempLabel(NULL);
9770 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9771 pic16_mov2f(AOP(result), AOP(left), 0);
9773 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9774 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9777 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9778 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9779 pic16_emitpLabel(tlbl->key);
9780 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9781 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9783 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9788 if (pic16_sameRegs(AOP(left),AOP(result))) {
9790 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9792 tlbl = newiTempLabel(NULL);
9793 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9794 genMultiAsm(POC_RRCF, result, size,1);
9795 pic16_emitpLabel(tlbl->key);
9796 genMultiAsm(POC_RLCF, result, size,0);
9797 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9799 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9803 //tlbl = newiTempLabel(NULL);
9805 //tlbl1 = newiTempLabel(NULL);
9807 //reAdjustPreg(AOP(result));
9809 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9810 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9811 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9813 //pic16_emitcode("add","a,acc");
9814 //pic16_aopPut(AOP(result),"a",offset++);
9816 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9818 // pic16_emitcode("rlc","a");
9819 // pic16_aopPut(AOP(result),"a",offset++);
9821 //reAdjustPreg(AOP(result));
9823 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9824 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9827 tlbl = newiTempLabel(NULL);
9828 tlbl1= newiTempLabel(NULL);
9830 size = AOP_SIZE(result);
9833 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9835 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9837 /* offset should be 0, 1 or 3 */
9839 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9841 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9843 pic16_emitpcode(POC_MOVWF, pctemp);
9846 pic16_emitpLabel(tlbl->key);
9849 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9851 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9853 pic16_emitpcode(POC_DECFSZ, pctemp);
9854 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9855 pic16_emitpLabel(tlbl1->key);
9857 pic16_popReleaseTempReg(pctemp,1);
9861 pic16_freeAsmop (right,NULL,ic,TRUE);
9862 pic16_freeAsmop(left,NULL,ic,TRUE);
9863 pic16_freeAsmop(result,NULL,ic,TRUE);
9867 /*-----------------------------------------------------------------*/
9868 /* genrshOne - right shift a one byte quantity by known count */
9869 /*-----------------------------------------------------------------*/
9870 static void genrshOne (operand *result, operand *left,
9871 int shCount, int sign)
9873 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9874 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9877 /*-----------------------------------------------------------------*/
9878 /* genrshTwo - right shift two bytes by known amount != 0 */
9879 /*-----------------------------------------------------------------*/
9880 static void genrshTwo (operand *result,operand *left,
9881 int shCount, int sign)
9883 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9884 /* if shCount >= 8 */
9888 shiftR1Left2Result(left, MSB16, result, LSB,
9891 movLeft2Result(left, MSB16, result, LSB);
9893 pic16_addSign (result, 1, sign);
9896 /* 1 <= shCount <= 7 */
9898 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9901 /*-----------------------------------------------------------------*/
9902 /* shiftRLong - shift right one long from left to result */
9903 /* offl = LSB or MSB16 */
9904 /*-----------------------------------------------------------------*/
9905 static void shiftRLong (operand *left, int offl,
9906 operand *result, int sign)
9908 int size = AOP_SIZE(result);
9909 int same = pic16_sameRegs(AOP(left),AOP(result));
9911 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9913 if (same && (offl == MSB16)) { //shift one byte right
9914 for(i=MSB16;i<size;i++) {
9915 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9916 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9921 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9927 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9929 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9930 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9934 /* add sign of "a" */
9935 pic16_addSign(result, MSB32, sign);
9939 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9941 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9942 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9946 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9948 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9949 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9953 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9956 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9957 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9962 /*-----------------------------------------------------------------*/
9963 /* genrshFour - shift four byte by a known amount != 0 */
9964 /*-----------------------------------------------------------------*/
9965 static void genrshFour (operand *result, operand *left,
9966 int shCount, int sign)
9968 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9969 /* if shifting more that 3 bytes */
9970 if(shCount >= 24 ) {
9973 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9975 movLeft2Result(left, MSB32, result, LSB);
9977 pic16_addSign(result, MSB16, sign);
9979 else if(shCount >= 16){
9982 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9984 movLeft2Result(left, MSB24, result, LSB);
9985 movLeft2Result(left, MSB32, result, MSB16);
9987 pic16_addSign(result, MSB24, sign);
9989 else if(shCount >= 8){
9992 shiftRLong(left, MSB16, result, sign);
9993 else if(shCount == 0){
9994 movLeft2Result(left, MSB16, result, LSB);
9995 movLeft2Result(left, MSB24, result, MSB16);
9996 movLeft2Result(left, MSB32, result, MSB24);
9997 pic16_addSign(result, MSB32, sign);
9999 else{ //shcount >= 2
10000 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10001 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10002 /* the last shift is signed */
10003 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10004 pic16_addSign(result, MSB32, sign);
10007 else{ /* 1 <= shCount <= 7 */
10009 shiftRLong(left, LSB, result, sign);
10011 shiftRLong(result, LSB, result, sign);
10014 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10015 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10016 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10021 /*-----------------------------------------------------------------*/
10022 /* genRightShiftLiteral - right shifting by known count */
10023 /*-----------------------------------------------------------------*/
10024 static void genRightShiftLiteral (operand *left,
10030 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10031 int lsize,res_size;
10033 pic16_freeAsmop(right,NULL,ic,TRUE);
10035 pic16_aopOp(left,ic,FALSE);
10036 pic16_aopOp(result,ic,TRUE);
10038 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10041 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10045 lsize = pic16_getDataSize(left);
10046 res_size = pic16_getDataSize(result);
10047 /* test the LEFT size !!! */
10049 /* I suppose that the left size >= result size */
10051 assert (res_size <= lsize);
10052 while (res_size--) {
10053 pic16_mov2f (AOP(result), AOP(left), res_size);
10057 else if(shCount >= (lsize * 8)){
10059 if(res_size == 1) {
10060 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10062 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10063 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10068 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10069 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10070 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10072 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10077 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10082 switch (res_size) {
10084 genrshOne (result,left,shCount,sign);
10088 genrshTwo (result,left,shCount,sign);
10092 genrshFour (result,left,shCount,sign);
10100 pic16_freeAsmop(left,NULL,ic,TRUE);
10101 pic16_freeAsmop(result,NULL,ic,TRUE);
10104 #if !(USE_GENERIC_SIGNED_SHIFT)
10105 /*-----------------------------------------------------------------*/
10106 /* genSignedRightShift - right shift of signed number */
10107 /*-----------------------------------------------------------------*/
10108 static void genSignedRightShift (iCode *ic)
10110 operand *right, *left, *result;
10113 symbol *tlbl, *tlbl1 ;
10116 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10118 /* we do it the hard way put the shift count in b
10119 and loop thru preserving the sign */
10120 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10122 right = IC_RIGHT(ic);
10123 left = IC_LEFT(ic);
10124 result = IC_RESULT(ic);
10126 pic16_aopOp(right,ic,FALSE);
10127 pic16_aopOp(left,ic,FALSE);
10128 pic16_aopOp(result,ic,FALSE);
10131 if ( AOP_TYPE(right) == AOP_LIT) {
10132 genRightShiftLiteral (left,right,result,ic,1);
10135 /* shift count is unknown then we have to form
10136 a loop get the loop count in B : Note: we take
10137 only the lower order byte since shifting
10138 more that 32 bits make no sense anyway, ( the
10139 largest size of an object can be only 32 bits ) */
10141 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10142 //pic16_emitcode("inc","b");
10143 //pic16_freeAsmop (right,NULL,ic,TRUE);
10144 //pic16_aopOp(left,ic,FALSE);
10145 //pic16_aopOp(result,ic,FALSE);
10147 /* now move the left to the result if they are not the
10149 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10150 AOP_SIZE(result) > 1) {
10152 size = AOP_SIZE(result);
10156 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10157 if (*l == '@' && IS_AOP_PREG(result)) {
10159 pic16_emitcode("mov","a,%s",l);
10160 pic16_aopPut(AOP(result),"a",offset);
10162 pic16_aopPut(AOP(result),l,offset);
10164 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10165 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10171 /* mov the highest order bit to OVR */
10172 tlbl = newiTempLabel(NULL);
10173 tlbl1= newiTempLabel(NULL);
10175 size = AOP_SIZE(result);
10178 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10180 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10182 /* offset should be 0, 1 or 3 */
10183 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10185 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10187 pic16_emitpcode(POC_MOVWF, pctemp);
10190 pic16_emitpLabel(tlbl->key);
10192 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10193 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10196 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10199 pic16_emitpcode(POC_DECFSZ, pctemp);
10200 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10201 pic16_emitpLabel(tlbl1->key);
10203 pic16_popReleaseTempReg(pctemp,1);
10205 size = AOP_SIZE(result);
10207 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10208 pic16_emitcode("rlc","a");
10209 pic16_emitcode("mov","ov,c");
10210 /* if it is only one byte then */
10212 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10214 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10215 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10216 pic16_emitcode("mov","c,ov");
10217 pic16_emitcode("rrc","a");
10218 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10219 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10220 pic16_aopPut(AOP(result),"a",0);
10224 reAdjustPreg(AOP(result));
10225 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10226 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10227 pic16_emitcode("mov","c,ov");
10229 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10231 pic16_emitcode("rrc","a");
10232 pic16_aopPut(AOP(result),"a",offset--);
10234 reAdjustPreg(AOP(result));
10235 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10236 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10241 pic16_freeAsmop(left,NULL,ic,TRUE);
10242 pic16_freeAsmop(result,NULL,ic,TRUE);
10243 pic16_freeAsmop(right,NULL,ic,TRUE);
10247 #if !(USE_GENERIC_SIGNED_SHIFT)
10248 #warning This implementation of genRightShift() is incomplete!
10249 /*-----------------------------------------------------------------*/
10250 /* genRightShift - generate code for right shifting */
10251 /*-----------------------------------------------------------------*/
10252 static void genRightShift (iCode *ic)
10254 operand *right, *left, *result;
10258 symbol *tlbl, *tlbl1 ;
10260 /* if signed then we do it the hard way preserve the
10261 sign bit moving it inwards */
10262 letype = getSpec(operandType(IC_LEFT(ic)));
10263 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10265 if (!SPEC_USIGN(letype)) {
10266 genSignedRightShift (ic);
10270 /* signed & unsigned types are treated the same : i.e. the
10271 signed is NOT propagated inwards : quoting from the
10272 ANSI - standard : "for E1 >> E2, is equivalent to division
10273 by 2**E2 if unsigned or if it has a non-negative value,
10274 otherwise the result is implementation defined ", MY definition
10275 is that the sign does not get propagated */
10277 right = IC_RIGHT(ic);
10278 left = IC_LEFT(ic);
10279 result = IC_RESULT(ic);
10281 pic16_aopOp(right,ic,FALSE);
10283 /* if the shift count is known then do it
10284 as efficiently as possible */
10285 if (AOP_TYPE(right) == AOP_LIT) {
10286 genRightShiftLiteral (left,right,result,ic, 0);
10290 /* shift count is unknown then we have to form
10291 a loop get the loop count in B : Note: we take
10292 only the lower order byte since shifting
10293 more that 32 bits make no sense anyway, ( the
10294 largest size of an object can be only 32 bits ) */
10296 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10297 pic16_emitcode("inc","b");
10298 pic16_aopOp(left,ic,FALSE);
10299 pic16_aopOp(result,ic,FALSE);
10301 /* now move the left to the result if they are not the
10303 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10304 AOP_SIZE(result) > 1) {
10306 size = AOP_SIZE(result);
10309 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10310 if (*l == '@' && IS_AOP_PREG(result)) {
10312 pic16_emitcode("mov","a,%s",l);
10313 pic16_aopPut(AOP(result),"a",offset);
10315 pic16_aopPut(AOP(result),l,offset);
10320 tlbl = newiTempLabel(NULL);
10321 tlbl1= newiTempLabel(NULL);
10322 size = AOP_SIZE(result);
10325 /* if it is only one byte then */
10328 tlbl = newiTempLabel(NULL);
10329 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10330 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10331 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10334 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10335 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10336 pic16_emitpLabel(tlbl->key);
10337 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10338 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10340 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10345 reAdjustPreg(AOP(result));
10346 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10347 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10350 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10352 pic16_emitcode("rrc","a");
10353 pic16_aopPut(AOP(result),"a",offset--);
10355 reAdjustPreg(AOP(result));
10357 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10358 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10361 pic16_freeAsmop(left,NULL,ic,TRUE);
10362 pic16_freeAsmop (right,NULL,ic,TRUE);
10363 pic16_freeAsmop(result,NULL,ic,TRUE);
10367 #if (USE_GENERIC_SIGNED_SHIFT)
10368 /*-----------------------------------------------------------------*/
10369 /* genGenericShift - generates code for left or right shifting */
10370 /*-----------------------------------------------------------------*/
10371 static void genGenericShift (iCode *ic, int isShiftLeft) {
10372 operand *left,*right, *result;
10374 int sign, signedCount;
10375 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10376 PIC_OPCODE pos_shift, neg_shift;
10380 right = IC_RIGHT(ic);
10381 left = IC_LEFT(ic);
10382 result = IC_RESULT(ic);
10384 pic16_aopOp(right,ic,FALSE);
10385 pic16_aopOp(left,ic,FALSE);
10386 pic16_aopOp(result,ic,TRUE);
10388 sign = !SPEC_USIGN(operandType (left));
10389 signedCount = !SPEC_USIGN(operandType (right));
10391 /* if the shift count is known then do it
10392 as efficiently as possible */
10393 if (AOP_TYPE(right) == AOP_LIT) {
10394 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10395 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10396 // we should modify right->aopu.aop_lit here!
10397 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10398 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10400 pic16_genLeftShiftLiteral (left,right,result,ic);
10402 genRightShiftLiteral (left,right,result,ic, sign);
10405 } // if (right is literal)
10407 /* shift count is unknown then we have to form a loop.
10408 * Note: we take only the lower order byte since shifting
10409 * more than 32 bits make no sense anyway, ( the
10410 * largest size of an object can be only 32 bits )
10411 * Note: we perform arithmetic shifts if the left operand is
10412 * signed and we do an (effective) right shift, i. e. we
10413 * shift in the sign bit from the left. */
10415 label_complete = newiTempLabel ( NULL );
10416 label_loop_pos = newiTempLabel ( NULL );
10417 label_loop_neg = NULL;
10418 label_negative = NULL;
10419 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10420 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10423 // additional labels needed
10424 label_loop_neg = newiTempLabel ( NULL );
10425 label_negative = newiTempLabel ( NULL );
10428 // copy source to result -- this will effectively truncate the left operand to the size of result!
10429 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10430 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10431 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10432 pic16_mov2f (AOP(result),AOP(left), offset);
10435 // if result is longer than left, fill with zeros (or sign)
10436 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10437 if (sign && AOP_SIZE(left) > 0) {
10438 // shift signed operand -- fill with sign
10439 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10440 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10441 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10442 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10443 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10446 // shift unsigned operand -- fill result with zeros
10447 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10448 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10451 } // if (size mismatch)
10453 pic16_mov2w (AOP(right), 0);
10454 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10455 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10458 // perform a shift by one (shift count is positive)
10459 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10460 // 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])
10461 pic16_emitpLabel (label_loop_pos->key);
10463 if (sign && (pos_shift == POC_RRCF)) {
10464 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10467 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10468 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10469 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10471 // perform a shift by one (shift count is positive)
10472 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10473 // 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])
10474 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10475 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10477 pic16_emitpLabel (label_loop_pos->key);
10478 if (sign && (pos_shift == POC_RRCF)) {
10479 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10482 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10483 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10484 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10485 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10489 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10491 pic16_emitpLabel (label_negative->key);
10492 // perform a shift by -1 (shift count is negative)
10493 // 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)
10495 pic16_emitpLabel (label_loop_neg->key);
10496 if (sign && (neg_shift == POC_RRCF)) {
10497 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10500 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10501 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10502 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10503 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10504 } // if (signedCount)
10506 pic16_emitpLabel (label_complete->key);
10509 pic16_freeAsmop (right,NULL,ic,TRUE);
10510 pic16_freeAsmop(left,NULL,ic,TRUE);
10511 pic16_freeAsmop(result,NULL,ic,TRUE);
10514 static void genLeftShift (iCode *ic) {
10515 genGenericShift (ic, 1);
10518 static void genRightShift (iCode *ic) {
10519 genGenericShift (ic, 0);
10524 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10525 void pic16_loadFSR0(operand *op, int lit)
10527 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10528 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10530 assert (!OP_SYMBOL(op)->remat);
10531 // set up FSR0 with address of result
10532 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10533 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10537 /*----------------------------------------------------------------*/
10538 /* pic16_derefPtr - move one byte from the location ptr points to */
10539 /* to WREG (doWrite == 0) or one byte from WREG */
10540 /* to the location ptr points to (doWrite != 0) */
10541 /*----------------------------------------------------------------*/
10542 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10547 if (!fsr0_setup || !*fsr0_setup)
10549 pic16_loadFSR0( ptr, 0 );
10550 if (fsr0_setup) *fsr0_setup = 1;
10553 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10555 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10559 if (AOP(ptr)->aopu.aop_reg[2]) {
10560 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10561 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10562 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10563 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl)));
10564 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(ptr),2));
10565 pic16_callGenericPointerRW(doWrite, 1);
10567 // data pointer (just 2 byte given)
10568 if (!fsr0_setup || !*fsr0_setup)
10570 pic16_loadFSR0( ptr, 0 );
10571 if (fsr0_setup) *fsr0_setup = 1;
10574 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10576 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10581 assert (0 && "invalid pointer type specified");
10586 /*-----------------------------------------------------------------*/
10587 /* genUnpackBits - generates code for unpacking bits */
10588 /*-----------------------------------------------------------------*/
10589 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10592 sym_link *etype, *letype;
10593 int blen=0, bstr=0;
10596 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10597 etype = getSpec(operandType(result));
10598 letype = getSpec(operandType(left));
10600 // if(IS_BITFIELD(etype)) {
10601 blen = SPEC_BLEN(etype);
10602 bstr = SPEC_BSTR(etype);
10605 lbstr = SPEC_BSTR( letype );
10608 if((blen == 1) && (bstr < 8)) {
10609 /* it is a single bit, so use the appropriate bit instructions */
10610 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10612 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10614 // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10615 if(!IS_PTR(operandType(left))/* && OP_SYMBOL(left)->remat && (ptype == POINTER)*/) {
10616 /* workaround to reduce the extra lfsr instruction */
10617 pic16_emitpcode(POC_BTFSC,
10618 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10620 pic16_loadFSR0 (left, 0);
10621 pic16_emitpcode(POC_BTFSC,
10622 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10625 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10627 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10633 /* the following call to pic16_loadFSR0 is temporary until
10634 * optimization to handle single bit assignments is added
10635 * to the function. Until then use the old safe way! -- VR */
10637 if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
10638 // access symbol directly
10639 pic16_mov2w (AOP(left), 0);
10641 pic16_derefPtr (left, ptype, 0, NULL);
10644 /* if we have bitdisplacement then it fits */
10645 /* into this byte completely or if length is */
10646 /* less than a byte */
10647 if ((shCnt = SPEC_BSTR(etype)) ||
10648 (SPEC_BLEN(etype) <= 8)) {
10650 /* shift right acc */
10653 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10654 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10656 /* VR -- normally I would use the following, but since we use the hack,
10657 * to avoid the masking from AccRsh, why not mask it right now? */
10660 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10663 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10669 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10670 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10677 static void genDataPointerGet(operand *left,
10681 int size, offset = 0, leoffset=0 ;
10683 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10684 pic16_aopOp(result, ic, TRUE);
10688 size = AOP_SIZE(result);
10689 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10693 /* The following tests may save a redudant movff instruction when
10694 * accessing unions */
10696 /* if they are the same */
10697 if (operandsEqu (left, result)) {
10698 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10704 /* if they are the same registers */
10705 if (pic16_sameRegs(AOP(left),AOP(result))) {
10706 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10712 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10713 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10714 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10721 if ( AOP_TYPE(left) == AOP_PCODE) {
10722 fprintf(stderr,"genDataPointerGet %s, %d\n",
10723 AOP(left)->aopu.pcop->name,
10724 (AOP(left)->aopu.pcop->type == PO_DIR)?
10725 PCOR(AOP(left)->aopu.pcop)->instance:
10726 PCOI(AOP(left)->aopu.pcop)->offset);
10730 if(AOP(left)->aopu.pcop->type == PO_DIR)
10731 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10733 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10736 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10738 // pic16_DumpOp("(result)",result);
10739 if(is_LitAOp(AOP(result))) {
10740 pic16_mov2w(AOP(left), offset); // patch 8
10741 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10743 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10744 pic16_popGet(AOP(left), offset), //patch 8
10745 pic16_popGet(AOP(result), offset)));
10753 pic16_freeAsmop(result,NULL,ic,TRUE);
10758 /*-----------------------------------------------------------------*/
10759 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10760 /*-----------------------------------------------------------------*/
10761 static void genNearPointerGet (operand *left,
10765 // asmop *aop = NULL;
10766 //regs *preg = NULL ;
10767 sym_link *rtype, *retype;
10768 sym_link *ltype, *letype;
10772 rtype = operandType(result);
10773 retype= getSpec(rtype);
10774 ltype = operandType(left);
10775 letype= getSpec(ltype);
10777 pic16_aopOp(left,ic,FALSE);
10779 // pic16_DumpOp("(left)",left);
10780 // pic16_DumpOp("(result)",result);
10782 /* if left is rematerialisable and
10783 * result is not bit variable type and
10784 * the left is pointer to data space i.e
10785 * lower 128 bytes of space */
10787 if (AOP_TYPE(left) == AOP_PCODE
10788 && !IS_BITFIELD(retype)
10789 && DCL_TYPE(ltype) == POINTER) {
10791 genDataPointerGet (left,result,ic);
10792 pic16_freeAsmop(left, NULL, ic, TRUE);
10796 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10797 pic16_aopOp (result,ic,TRUE);
10799 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10802 if(IS_BITFIELD( retype )
10803 && (SPEC_BLEN(operandType(result))==1)
10807 int bitstrt, bytestrt;
10809 /* if this is bitfield of size 1, see if we are checking the value
10810 * of a single bit in an if-statement,
10811 * if yes, then don't generate usual code, but execute the
10812 * genIfx directly -- VR */
10816 /* CHECK: if next iCode is IFX
10817 * and current result operand is nextic's conditional operand
10818 * and current result operand live ranges ends at nextic's key number
10820 if((nextic->op == IFX)
10821 && (result == IC_COND(nextic))
10822 && (OP_LIVETO(result) == nextic->seq)
10823 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10825 /* everything is ok then */
10826 /* find a way to optimize the genIfx iCode */
10828 bytestrt = SPEC_BSTR(operandType(result))/8;
10829 bitstrt = SPEC_BSTR(operandType(result))%8;
10831 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10833 genIfxpCOpJump(nextic, jop);
10835 pic16_freeAsmop(left, NULL, ic, TRUE);
10836 pic16_freeAsmop(result, NULL, ic, TRUE);
10842 /* if bitfield then unpack the bits */
10843 if (IS_BITFIELD(letype))
10844 genUnpackBits (result, left, NULL, POINTER);
10846 /* we have can just get the values */
10847 int size = AOP_SIZE(result);
10850 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10852 pic16_loadFSR0( left, 0 );
10856 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10857 pic16_popGet(AOP(result), offset++)));
10859 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10860 pic16_popGet(AOP(result), offset++)));
10866 /* now some housekeeping stuff */
10868 /* we had to allocate for this iCode */
10869 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10870 pic16_freeAsmop(NULL,aop,ic,TRUE);
10872 /* we did not allocate which means left
10873 * already in a pointer register, then
10874 * if size > 0 && this could be used again
10875 * we have to point it back to where it
10877 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10878 if (AOP_SIZE(result) > 1
10879 && !OP_SYMBOL(left)->remat
10880 && ( OP_SYMBOL(left)->liveTo > ic->seq
10882 // int size = AOP_SIZE(result) - 1;
10884 // pic16_emitcode("dec","%s",rname);
10890 pic16_freeAsmop(left,NULL,ic,TRUE);
10891 pic16_freeAsmop(result,NULL,ic,TRUE);
10894 /*-----------------------------------------------------------------*/
10895 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10896 /*-----------------------------------------------------------------*/
10897 static void genPagedPointerGet (operand *left,
10902 regs *preg = NULL ;
10904 sym_link *rtype, *retype;
10906 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10908 rtype = operandType(result);
10909 retype= getSpec(rtype);
10911 pic16_aopOp(left,ic,FALSE);
10913 /* if the value is already in a pointer register
10914 then don't need anything more */
10915 if (!AOP_INPREG(AOP(left))) {
10916 /* otherwise get a free pointer register */
10918 preg = getFreePtr(ic,&aop,FALSE);
10919 pic16_emitcode("mov","%s,%s",
10921 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10922 rname = preg->name ;
10924 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10926 pic16_freeAsmop(left,NULL,ic,TRUE);
10927 pic16_aopOp (result,ic,TRUE);
10929 /* if bitfield then unpack the bits */
10930 if (IS_BITFIELD(retype))
10931 genUnpackBits (result,left,rname,PPOINTER);
10933 /* we have can just get the values */
10934 int size = AOP_SIZE(result);
10939 pic16_emitcode("movx","a,@%s",rname);
10940 pic16_aopPut(AOP(result),"a",offset);
10945 pic16_emitcode("inc","%s",rname);
10949 /* now some housekeeping stuff */
10951 /* we had to allocate for this iCode */
10952 pic16_freeAsmop(NULL,aop,ic,TRUE);
10954 /* we did not allocate which means left
10955 already in a pointer register, then
10956 if size > 0 && this could be used again
10957 we have to point it back to where it
10959 if (AOP_SIZE(result) > 1 &&
10960 !OP_SYMBOL(left)->remat &&
10961 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10963 int size = AOP_SIZE(result) - 1;
10965 pic16_emitcode("dec","%s",rname);
10970 pic16_freeAsmop(result,NULL,ic,TRUE);
10976 /* This code is not adjusted to PIC16 and fails utterly.
10977 * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10979 /*-----------------------------------------------------------------*/
10980 /* genFarPointerGet - gget value from far space */
10981 /*-----------------------------------------------------------------*/
10982 static void genFarPointerGet (operand *left,
10983 operand *result, iCode *ic)
10986 sym_link *retype = getSpec(operandType(result));
10988 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10990 pic16_aopOp(left,ic,FALSE);
10992 /* if the operand is already in dptr
10993 then we do nothing else we move the value to dptr */
10994 if (AOP_TYPE(left) != AOP_STR) {
10995 /* if this is remateriazable */
10996 if (AOP_TYPE(left) == AOP_IMMD)
10997 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10998 else { /* we need to get it byte by byte */
10999 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11000 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11001 if (options.model == MODEL_FLAT24)
11003 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11007 /* so dptr know contains the address */
11008 pic16_freeAsmop(left,NULL,ic,TRUE);
11009 pic16_aopOp(result,ic,TRUE);
11011 /* if bit then unpack */
11012 if (IS_BITFIELD(retype))
11013 genUnpackBits(result,left,"dptr",FPOINTER);
11015 size = AOP_SIZE(result);
11019 pic16_emitcode("movx","a,@dptr");
11020 pic16_aopPut(AOP(result),"a",offset++);
11022 pic16_emitcode("inc","dptr");
11026 pic16_freeAsmop(result,NULL,ic,TRUE);
11031 /*-----------------------------------------------------------------*/
11032 /* genCodePointerGet - get value from code space */
11033 /*-----------------------------------------------------------------*/
11034 static void genCodePointerGet (operand *left,
11035 operand *result, iCode *ic)
11038 sym_link *retype = getSpec(operandType(result));
11040 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11042 pic16_aopOp(left,ic,FALSE);
11044 /* if the operand is already in dptr
11045 then we do nothing else we move the value to dptr */
11046 if (AOP_TYPE(left) != AOP_STR) {
11047 /* if this is remateriazable */
11048 if (AOP_TYPE(left) == AOP_IMMD)
11049 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11050 else { /* we need to get it byte by byte */
11051 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11052 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11053 if (options.model == MODEL_FLAT24)
11055 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11059 /* so dptr know contains the address */
11060 pic16_freeAsmop(left,NULL,ic,TRUE);
11061 pic16_aopOp(result,ic,FALSE);
11063 /* if bit then unpack */
11064 if (IS_BITFIELD(retype))
11065 genUnpackBits(result,left,"dptr",CPOINTER);
11067 size = AOP_SIZE(result);
11071 pic16_emitcode("clr","a");
11072 pic16_emitcode("movc","a,@a+dptr");
11073 pic16_aopPut(AOP(result),"a",offset++);
11075 pic16_emitcode("inc","dptr");
11079 pic16_freeAsmop(result,NULL,ic,TRUE);
11084 /*-----------------------------------------------------------------*/
11085 /* genGenPointerGet - gget value from generic pointer space */
11086 /*-----------------------------------------------------------------*/
11087 static void genGenPointerGet (operand *left,
11088 operand *result, iCode *ic)
11090 int size, offset, lit;
11091 sym_link *retype = getSpec(operandType(result));
11093 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11094 pic16_aopOp(left,ic,FALSE);
11095 pic16_aopOp(result,ic,FALSE);
11096 size = AOP_SIZE(result);
11098 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11100 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11102 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11103 // load FSR0 from immediate
11104 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11106 // pic16_loadFSR0( left );
11111 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11113 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11120 else { /* we need to get it byte by byte */
11121 // set up FSR0 with address from left
11122 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11123 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11129 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11131 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11138 /* if bit then unpack */
11139 if (IS_BITFIELD(retype))
11140 genUnpackBits(result,left,"BAD",GPOINTER);
11143 pic16_freeAsmop(left,NULL,ic,TRUE);
11144 pic16_freeAsmop(result,NULL,ic,TRUE);
11150 /*-----------------------------------------------------------------*/
11151 /* genGenPointerGet - gget value from generic pointer space */
11152 /*-----------------------------------------------------------------*/
11153 static void genGenPointerGet (operand *left,
11154 operand *result, iCode *ic)
11156 int size, offset, lit;
11157 sym_link *letype = getSpec(operandType(left));
11159 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11160 pic16_aopOp(left,ic,FALSE);
11161 pic16_aopOp(result,ic,TRUE);
11162 size = AOP_SIZE(result);
11164 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11166 /* if bit then unpack */
11167 if (IS_BITFIELD(letype)) {
11168 genUnpackBits(result,left,"BAD",GPOINTER);
11172 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11174 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11175 // load FSR0 from immediate
11176 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11178 werror(W_POSSBUG2, __FILE__, __LINE__);
11183 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11185 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11192 } else { /* we need to get it byte by byte */
11194 /* set up WREG:PRODL:FSR0L with address from left */
11195 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11196 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11197 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11199 pic16_callGenericPointerRW(0, size);
11201 assignResultValue(result, 1);
11207 pic16_freeAsmop(left,NULL,ic,TRUE);
11208 pic16_freeAsmop(result,NULL,ic,TRUE);
11211 /*-----------------------------------------------------------------*/
11212 /* genConstPointerGet - get value from const generic pointer space */
11213 /*-----------------------------------------------------------------*/
11214 static void genConstPointerGet (operand *left,
11215 operand *result, iCode *ic)
11217 //sym_link *retype = getSpec(operandType(result));
11218 // symbol *albl = newiTempLabel(NULL); // patch 15
11219 // symbol *blbl = newiTempLabel(NULL); //
11220 // PIC_OPCODE poc; // patch 15
11224 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11225 pic16_aopOp(left,ic,FALSE);
11226 pic16_aopOp(result,ic,TRUE);
11227 size = AOP_SIZE(result);
11229 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11231 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11233 // set up table pointer
11234 if( (AOP_TYPE(left) == AOP_PCODE)
11235 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11236 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11238 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11239 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11240 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11241 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11242 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11243 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11245 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11246 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11247 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11251 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11252 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11256 pic16_freeAsmop(left,NULL,ic,TRUE);
11257 pic16_freeAsmop(result,NULL,ic,TRUE);
11261 /*-----------------------------------------------------------------*/
11262 /* genPointerGet - generate code for pointer get */
11263 /*-----------------------------------------------------------------*/
11264 static void genPointerGet (iCode *ic)
11266 operand *left, *result ;
11267 sym_link *type, *etype;
11272 left = IC_LEFT(ic);
11273 result = IC_RESULT(ic) ;
11275 /* depending on the type of pointer we need to
11276 move it to the correct pointer register */
11277 type = operandType(left);
11278 etype = getSpec(type);
11281 if (IS_PTR_CONST(type))
11283 if (IS_CODEPTR(type))
11285 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11287 /* if left is of type of pointer then it is simple */
11288 if (IS_PTR(type) && !IS_FUNC(type->next))
11289 p_type = DCL_TYPE(type);
11291 /* we have to go by the storage class */
11292 p_type = PTR_TYPE(SPEC_OCLS(etype));
11294 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11296 if (SPEC_OCLS(etype)->codesp ) {
11297 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11298 //p_type = CPOINTER ;
11300 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11301 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11302 /*p_type = FPOINTER ;*/
11304 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11305 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11306 /* p_type = PPOINTER; */
11308 if (SPEC_OCLS(etype) == idata ) {
11309 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11310 /* p_type = IPOINTER; */
11312 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11313 /* p_type = POINTER ; */
11317 /* now that we have the pointer type we assign
11318 the pointer values */
11323 genNearPointerGet (left,result,ic);
11327 genPagedPointerGet(left,result,ic);
11331 /* PICs do not support FAR pointers... */
11332 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11334 genFarPointerGet (left,result,ic);
11339 genConstPointerGet (left,result,ic);
11340 //pic16_emitcodePointerGet (left,result,ic);
11345 if (IS_PTR_CONST(type))
11346 genConstPointerGet (left,result,ic);
11349 genGenPointerGet (left,result,ic);
11353 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11354 "genPointerGet: illegal pointer type");
11359 /*-----------------------------------------------------------------*/
11360 /* genPackBits - generates code for packed bit storage */
11361 /*-----------------------------------------------------------------*/
11362 static void genPackBits (sym_link *etype , operand *result,
11364 char *rname, int p_type)
11372 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11373 blen = SPEC_BLEN(etype);
11374 bstr = SPEC_BSTR(etype);
11376 retype = getSpec(operandType(right));
11378 if(AOP_TYPE(right) == AOP_LIT) {
11379 if((blen == 1) && (bstr < 8)) {
11381 /* it is a single bit, so use the appropriate bit instructions */
11383 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11385 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11386 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11387 if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11388 /* workaround to reduce the extra lfsr instruction */
11390 pic16_emitpcode(POC_BSF,
11391 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11393 pic16_emitpcode(POC_BCF,
11394 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11397 pic16_loadFSR0(result, 0);
11399 pic16_emitpcode(POC_BSF,
11400 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11402 pic16_emitpcode(POC_BCF,
11403 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11409 /* move literal to W */
11410 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11413 if(IS_BITFIELD(retype)
11414 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11418 rblen = SPEC_BLEN( retype );
11419 rbstr = SPEC_BSTR( retype );
11422 if(IS_BITFIELD(etype)) {
11423 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11424 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11426 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11429 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11431 if(IS_BITFIELD(etype)) {
11432 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11434 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11437 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11441 /* move right to W */
11442 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11445 /* if the bit length is less than or */
11446 /* it exactly fits a byte then */
11447 if((shCnt=SPEC_BSTR(etype))
11448 || SPEC_BLEN(etype) <= 8 ) {
11449 int fsr0_setup = 0;
11451 if (blen != 8 || bstr != 0) {
11452 // we need to combine the value with the old value
11453 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11455 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11456 SPEC_BSTR(etype), SPEC_BLEN(etype));
11458 /* shift left acc */
11461 /* using PRODH as a temporary register here */
11462 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11464 if (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) {
11465 /* access symbol directly */
11466 pic16_mov2w (AOP(result), 0);
11468 /* get old value */
11469 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11472 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11473 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11474 (unsigned char)(0xff >> (8-bstr))) ));
11475 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11476 } // if (blen != 8 || bstr != 0)
11478 /* write new value back */
11479 if (IS_SYMOP(result) & !IS_PTR(operandType(result))) {
11480 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11482 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11491 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11492 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11497 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11498 rLen = SPEC_BLEN(etype)-8;
11500 /* now generate for lengths greater than one byte */
11504 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11510 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11516 pic16_emitcode("movx","@dptr,a");
11521 DEBUGpic16_emitcode(";lcall","__gptrput");
11529 pic16_mov2w(AOP(right), offset++);
11532 /* last last was not complete */
11534 /* save the byte & read byte */
11537 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11538 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11543 pic16_emitcode ("mov","b,a");
11544 pic16_emitcode("movx","a,@dptr");
11548 pic16_emitcode ("push","b");
11549 pic16_emitcode ("push","acc");
11550 pic16_emitcode ("lcall","__gptrget");
11551 pic16_emitcode ("pop","b");
11557 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11558 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11559 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11560 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11561 // pic16_emitcode ("orl","a,b");
11564 // if (p_type == GPOINTER)
11565 // pic16_emitcode("pop","b");
11570 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11571 // pic16_emitcode("mov","@%s,a",rname);
11575 pic16_emitcode("movx","@dptr,a");
11579 DEBUGpic16_emitcode(";lcall","__gptrput");
11586 // pic16_freeAsmop(right, NULL, ic, TRUE);
11588 /*-----------------------------------------------------------------*/
11589 /* genDataPointerSet - remat pointer to data space */
11590 /*-----------------------------------------------------------------*/
11591 static void genDataPointerSet(operand *right,
11595 int size, offset = 0, resoffset=0 ;
11597 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11598 pic16_aopOp(right,ic,FALSE);
11600 size = AOP_SIZE(right);
11602 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11605 if ( AOP_TYPE(result) == AOP_PCODE) {
11606 fprintf(stderr,"genDataPointerSet %s, %d\n",
11607 AOP(result)->aopu.pcop->name,
11608 (AOP(result)->aopu.pcop->type == PO_DIR)?
11609 PCOR(AOP(result)->aopu.pcop)->instance:
11610 PCOI(AOP(result)->aopu.pcop)->offset);
11614 if(AOP(result)->aopu.pcop->type == PO_DIR)
11615 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11618 if (AOP_TYPE(right) == AOP_LIT) {
11621 if(!IS_FLOAT(operandType( right )))
11622 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11625 unsigned long lit_int;
11629 /* take care if literal is a float */
11630 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11631 lit = info.lit_int;
11634 lit = lit >> (8*offset);
11636 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11637 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11639 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11642 pic16_mov2w(AOP(right), offset);
11643 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11649 pic16_freeAsmop(right,NULL,ic,TRUE);
11654 /*-----------------------------------------------------------------*/
11655 /* genNearPointerSet - pic16_emitcode for near pointer put */
11656 /*-----------------------------------------------------------------*/
11657 static void genNearPointerSet (operand *right,
11663 sym_link *ptype = operandType(result);
11664 sym_link *resetype;
11666 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11667 retype= getSpec(operandType(right));
11668 resetype = getSpec(operandType(result));
11670 pic16_aopOp(result,ic,FALSE);
11672 /* if the result is rematerializable &
11673 * in data space & not a bit variable */
11675 /* and result is not a bit variable */
11676 if (AOP_TYPE(result) == AOP_PCODE
11677 // && AOP_TYPE(result) == AOP_IMMD
11678 && DCL_TYPE(ptype) == POINTER
11679 && !IS_BITFIELD(retype)
11680 && !IS_BITFIELD(resetype)) {
11682 genDataPointerSet (right,result,ic);
11683 pic16_freeAsmop(result,NULL,ic,TRUE);
11687 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11688 pic16_aopOp(right,ic,FALSE);
11689 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11691 /* if bitfield then unpack the bits */
11692 if (IS_BITFIELD(resetype)) {
11693 genPackBits (resetype, result, right, NULL, POINTER);
11695 /* we have can just get the values */
11696 int size = AOP_SIZE(right);
11699 pic16_loadFSR0(result, 0);
11701 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11703 if (AOP_TYPE(right) == AOP_LIT) {
11704 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11706 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11708 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11710 } else { // no literal
11712 pic16_emitpcode(POC_MOVFF,
11713 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11714 pic16_popCopyReg(&pic16_pc_postinc0)));
11716 pic16_emitpcode(POC_MOVFF,
11717 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11718 pic16_popCopyReg(&pic16_pc_indf0)));
11725 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11726 /* now some housekeeping stuff */
11728 /* we had to allocate for this iCode */
11729 pic16_freeAsmop(NULL,aop,ic,TRUE);
11731 /* we did not allocate which means left
11732 * already in a pointer register, then
11733 * if size > 0 && this could be used again
11734 * we have to point it back to where it
11736 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11737 if (AOP_SIZE(right) > 1
11738 && !OP_SYMBOL(result)->remat
11739 && ( OP_SYMBOL(result)->liveTo > ic->seq
11742 int size = AOP_SIZE(right) - 1;
11745 pic16_emitcode("decf","fsr0,f");
11746 //pic16_emitcode("dec","%s",rname);
11750 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11753 pic16_freeAsmop(right,NULL,ic,TRUE);
11754 pic16_freeAsmop(result,NULL,ic,TRUE);
11757 /*-----------------------------------------------------------------*/
11758 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11759 /*-----------------------------------------------------------------*/
11760 static void genPagedPointerSet (operand *right,
11765 regs *preg = NULL ;
11769 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11771 retype= getSpec(operandType(right));
11773 pic16_aopOp(result,ic,FALSE);
11775 /* if the value is already in a pointer register
11776 then don't need anything more */
11777 if (!AOP_INPREG(AOP(result))) {
11778 /* otherwise get a free pointer register */
11780 preg = getFreePtr(ic,&aop,FALSE);
11781 pic16_emitcode("mov","%s,%s",
11783 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11784 rname = preg->name ;
11786 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11788 pic16_freeAsmop(result,NULL,ic,TRUE);
11789 pic16_aopOp (right,ic,FALSE);
11791 /* if bitfield then unpack the bits */
11792 if (IS_BITFIELD(retype))
11793 genPackBits (retype,result,right,rname,PPOINTER);
11795 /* we have can just get the values */
11796 int size = AOP_SIZE(right);
11800 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11803 pic16_emitcode("movx","@%s,a",rname);
11806 pic16_emitcode("inc","%s",rname);
11812 /* now some housekeeping stuff */
11814 /* we had to allocate for this iCode */
11815 pic16_freeAsmop(NULL,aop,ic,TRUE);
11817 /* we did not allocate which means left
11818 already in a pointer register, then
11819 if size > 0 && this could be used again
11820 we have to point it back to where it
11822 if (AOP_SIZE(right) > 1 &&
11823 !OP_SYMBOL(result)->remat &&
11824 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11826 int size = AOP_SIZE(right) - 1;
11828 pic16_emitcode("dec","%s",rname);
11833 pic16_freeAsmop(right,NULL,ic,TRUE);
11839 /* This code is not adjusted to PIC16 and fails utterly...
11840 * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11842 /*-----------------------------------------------------------------*/
11843 /* genFarPointerSet - set value from far space */
11844 /*-----------------------------------------------------------------*/
11845 static void genFarPointerSet (operand *right,
11846 operand *result, iCode *ic)
11849 sym_link *retype = getSpec(operandType(right));
11851 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11852 pic16_aopOp(result,ic,FALSE);
11854 /* if the operand is already in dptr
11855 then we do nothing else we move the value to dptr */
11856 if (AOP_TYPE(result) != AOP_STR) {
11857 /* if this is remateriazable */
11858 if (AOP_TYPE(result) == AOP_IMMD)
11859 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11860 else { /* we need to get it byte by byte */
11861 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11862 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11863 if (options.model == MODEL_FLAT24)
11865 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11869 /* so dptr know contains the address */
11870 pic16_freeAsmop(result,NULL,ic,TRUE);
11871 pic16_aopOp(right,ic,FALSE);
11873 /* if bit then unpack */
11874 if (IS_BITFIELD(retype))
11875 genPackBits(retype,result,right,"dptr",FPOINTER);
11877 size = AOP_SIZE(right);
11881 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11883 pic16_emitcode("movx","@dptr,a");
11885 pic16_emitcode("inc","dptr");
11889 pic16_freeAsmop(right,NULL,ic,TRUE);
11893 /*-----------------------------------------------------------------*/
11894 /* genGenPointerSet - set value from generic pointer space */
11895 /*-----------------------------------------------------------------*/
11897 static void genGenPointerSet (operand *right,
11898 operand *result, iCode *ic)
11900 int i, size, offset, lit;
11901 sym_link *retype = getSpec(operandType(right));
11903 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11905 pic16_aopOp(result,ic,FALSE);
11906 pic16_aopOp(right,ic,FALSE);
11907 size = AOP_SIZE(right);
11910 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11912 /* if the operand is already in dptr
11913 then we do nothing else we move the value to dptr */
11914 if (AOP_TYPE(result) != AOP_STR) {
11915 /* if this is remateriazable */
11916 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11917 // WARNING: anythig until "else" is untested!
11918 if (AOP_TYPE(result) == AOP_IMMD) {
11919 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11920 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11921 // load FSR0 from immediate
11922 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11926 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11928 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11934 else { /* we need to get it byte by byte */
11935 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11936 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11938 // set up FSR0 with address of result
11939 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11940 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11942 /* hack hack! see if this the FSR. If so don't load W */
11943 if(AOP_TYPE(right) != AOP_ACC) {
11945 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11947 if(AOP_TYPE(right) == AOP_LIT)
11950 // note: pic16_popGet handles sign extension
11951 for(i=0;i<size;i++) {
11952 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11954 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11956 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11961 for(i=0;i<size;i++) {
11963 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11964 pic16_popCopyReg(&pic16_pc_postinc0)));
11966 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11967 pic16_popCopyReg(&pic16_pc_indf0)));
11973 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11974 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11976 } // if (AOP_TYPE(result) != AOP_IMMD)
11978 } // if (AOP_TYPE(result) != AOP_STR)
11979 /* so dptr know contains the address */
11982 /* if bit then unpack */
11983 if (IS_BITFIELD(retype))
11984 genPackBits(retype,result,right,"dptr",GPOINTER);
11986 size = AOP_SIZE(right);
11989 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11991 // set up FSR0 with address of result
11992 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11993 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11996 if (AOP_TYPE(right) == AOP_LIT) {
11997 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11999 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12001 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12003 } else { // no literal
12005 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12007 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12015 pic16_freeAsmop(right,NULL,ic,TRUE);
12016 pic16_freeAsmop(result,NULL,ic,TRUE);
12020 static void genGenPointerSet (operand *right,
12021 operand *result, iCode *ic)
12024 sym_link *retype = getSpec(operandType(result));
12026 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12028 pic16_aopOp(result,ic,FALSE);
12029 pic16_aopOp(right,ic,FALSE);
12030 size = AOP_SIZE(right);
12032 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12035 /* if bit then unpack */
12036 if (IS_BITFIELD(retype)) {
12037 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12038 genPackBits(retype,result,right,"dptr",GPOINTER);
12042 size = AOP_SIZE(right);
12044 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12047 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12049 /* value of right+0 is placed on stack, which will be retrieved
12050 * by the support function this restoring the stack. The important
12051 * thing is that there is no need to manually restore stack pointer
12053 pushaop(AOP(right), 0);
12054 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12055 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12056 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12057 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12059 /* load address to write to in WREG:FSR0H:FSR0L */
12060 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12061 pic16_popCopyReg(&pic16_pc_fsr0l)));
12062 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12063 pic16_popCopyReg(&pic16_pc_prodl)));
12064 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12066 pic16_callGenericPointerRW(1, size);
12069 pic16_freeAsmop(right,NULL,ic,TRUE);
12070 pic16_freeAsmop(result,NULL,ic,TRUE);
12073 /*-----------------------------------------------------------------*/
12074 /* genPointerSet - stores the value into a pointer location */
12075 /*-----------------------------------------------------------------*/
12076 static void genPointerSet (iCode *ic)
12078 operand *right, *result ;
12079 sym_link *type, *etype;
12084 right = IC_RIGHT(ic);
12085 result = IC_RESULT(ic) ;
12087 /* depending on the type of pointer we need to
12088 move it to the correct pointer register */
12089 type = operandType(result);
12090 etype = getSpec(type);
12092 /* if left is of type of pointer then it is simple */
12093 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12094 p_type = DCL_TYPE(type);
12097 /* we have to go by the storage class */
12098 p_type = PTR_TYPE(SPEC_OCLS(etype));
12100 /* if (SPEC_OCLS(etype)->codesp ) { */
12101 /* p_type = CPOINTER ; */
12104 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12105 /* p_type = FPOINTER ; */
12107 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12108 /* p_type = PPOINTER ; */
12110 /* if (SPEC_OCLS(etype) == idata ) */
12111 /* p_type = IPOINTER ; */
12113 /* p_type = POINTER ; */
12116 /* now that we have the pointer type we assign
12117 the pointer values */
12122 genNearPointerSet (right,result,ic);
12126 genPagedPointerSet (right,result,ic);
12130 /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12132 genFarPointerSet (right,result,ic);
12137 genGenPointerSet (right,result,ic);
12141 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12142 "genPointerSet: illegal pointer type");
12146 /*-----------------------------------------------------------------*/
12147 /* genIfx - generate code for Ifx statement */
12148 /*-----------------------------------------------------------------*/
12149 static void genIfx (iCode *ic, iCode *popIc)
12151 operand *cond = IC_COND(ic);
12156 pic16_aopOp(cond,ic,FALSE);
12158 /* get the value into acc */
12159 if (AOP_TYPE(cond) != AOP_CRY)
12160 pic16_toBoolean(cond);
12163 /* the result is now in the accumulator */
12164 pic16_freeAsmop(cond,NULL,ic,TRUE);
12166 /* if there was something to be popped then do it */
12170 /* if the condition is a bit variable */
12171 if (isbit && IS_ITEMP(cond) &&
12173 genIfxJump(ic,"c");
12174 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12176 if (isbit && !IS_ITEMP(cond))
12177 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12179 genIfxJump(ic,"a");
12184 /*-----------------------------------------------------------------*/
12185 /* genAddrOf - generates code for address of */
12186 /*-----------------------------------------------------------------*/
12187 static void genAddrOf (iCode *ic)
12189 operand *result, *left;
12191 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12192 pCodeOp *pcop0, *pcop1, *pcop2;
12196 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12198 sym = OP_SYMBOL( IC_LEFT(ic) );
12201 /* get address of symbol on stack */
12202 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12204 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12205 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12208 // operands on stack are accessible via "FSR2 + index" with index
12209 // starting at 2 for arguments and growing from 0 downwards for
12210 // local variables (index == 0 is not assigned so we add one here)
12212 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12214 assert (soffs < 0);
12217 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12218 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12219 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12220 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12221 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12222 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12223 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12229 // if(pic16_debug_verbose) {
12230 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12231 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12234 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12235 size = AOP_SIZE(IC_RESULT(ic));
12237 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12238 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12239 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12242 pic16_emitpcode(POC_MOVLW, pcop0);
12243 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12244 pic16_emitpcode(POC_MOVLW, pcop1);
12245 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12246 pic16_emitpcode(POC_MOVLW, pcop2);
12247 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12250 pic16_emitpcode(POC_MOVLW, pcop0);
12251 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12252 pic16_emitpcode(POC_MOVLW, pcop1);
12253 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12255 pic16_emitpcode(POC_MOVLW, pcop0);
12256 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12259 pic16_freeAsmop(left, NULL, ic, FALSE);
12261 pic16_freeAsmop(result,NULL,ic,TRUE);
12266 /*-----------------------------------------------------------------*/
12267 /* genFarFarAssign - assignment when both are in far space */
12268 /*-----------------------------------------------------------------*/
12269 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12271 int size = AOP_SIZE(right);
12274 /* first push the right side on to the stack */
12276 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12278 pic16_emitcode ("push","acc");
12281 pic16_freeAsmop(right,NULL,ic,FALSE);
12282 /* now assign DPTR to result */
12283 pic16_aopOp(result,ic,FALSE);
12284 size = AOP_SIZE(result);
12286 pic16_emitcode ("pop","acc");
12287 pic16_aopPut(AOP(result),"a",--offset);
12289 pic16_freeAsmop(result,NULL,ic,FALSE);
12294 /*-----------------------------------------------------------------*/
12295 /* genAssign - generate code for assignment */
12296 /*-----------------------------------------------------------------*/
12297 static void genAssign (iCode *ic)
12299 operand *result, *right;
12300 int size, offset,know_W;
12301 unsigned long lit = 0L;
12303 result = IC_RESULT(ic);
12304 right = IC_RIGHT(ic) ;
12308 /* if they are the same */
12309 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12312 /* reversed order operands are aopOp'ed so that result operand
12313 * is effective in case right is a stack symbol. This maneauver
12314 * allows to use the _G.resDirect flag later */
12315 pic16_aopOp(result,ic,TRUE);
12316 pic16_aopOp(right,ic,FALSE);
12318 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12320 /* if they are the same registers */
12321 if (pic16_sameRegs(AOP(right),AOP(result)))
12324 /* if the result is a bit */
12325 if (AOP_TYPE(result) == AOP_CRY) {
12326 /* if the right size is a literal then
12327 we know what the value is */
12328 if (AOP_TYPE(right) == AOP_LIT) {
12330 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12331 pic16_popGet(AOP(result),0));
12333 if (((int) operandLitValue(right)))
12334 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12335 AOP(result)->aopu.aop_dir,
12336 AOP(result)->aopu.aop_dir);
12338 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12339 AOP(result)->aopu.aop_dir,
12340 AOP(result)->aopu.aop_dir);
12344 /* the right is also a bit variable */
12345 if (AOP_TYPE(right) == AOP_CRY) {
12346 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12347 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12348 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12350 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12351 AOP(result)->aopu.aop_dir,
12352 AOP(result)->aopu.aop_dir);
12353 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12354 AOP(right)->aopu.aop_dir,
12355 AOP(right)->aopu.aop_dir);
12356 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12357 AOP(result)->aopu.aop_dir,
12358 AOP(result)->aopu.aop_dir);
12362 /* we need to or */
12363 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12364 pic16_toBoolean(right);
12366 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12367 //pic16_aopPut(AOP(result),"a",0);
12371 /* bit variables done */
12373 size = AOP_SIZE(result);
12376 if(AOP_TYPE(right) == AOP_LIT) {
12377 if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12378 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12381 unsigned long lit_int;
12386 if(IS_FIXED16X16(operandType(right))) {
12387 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12389 /* take care if literal is a float */
12390 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12391 lit = info.lit_int;
12396 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12397 // sizeof(unsigned long int), sizeof(float));
12400 if (AOP_TYPE(right) == AOP_REG) {
12401 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12403 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12408 /* when do we have to read the program memory?
12409 * - if right itself is a symbol in code space
12410 * (we don't care what it points to if it's a pointer)
12411 * - AND right is not a function (we would want its address)
12413 if(AOP_TYPE(right) != AOP_LIT
12414 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12415 && !IS_FUNC(OP_SYM_TYPE(right))
12416 && !IS_ITEMP(right))
12418 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12419 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12421 // set up table pointer
12422 if(is_LitOp(right)) {
12423 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12424 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12425 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12426 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12427 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12428 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12429 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12431 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12432 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12433 pic16_popCopyReg(&pic16_pc_tblptrl)));
12434 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12435 pic16_popCopyReg(&pic16_pc_tblptrh)));
12436 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12437 pic16_popCopyReg(&pic16_pc_tblptru)));
12440 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12441 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12443 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12444 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12445 pic16_popGet(AOP(result),offset)));
12449 /* FIXME: for pointers we need to extend differently (according
12450 * to pointer type DATA/CODE/EEPROM/... :*/
12451 size = getSize(OP_SYM_TYPE(right));
12452 if(AOP_SIZE(result) > size) {
12453 size = AOP_SIZE(result) - size;
12455 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12465 /* VR - What is this?! */
12466 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12467 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12468 if(aopIdx(AOP(result),0) == 4) {
12470 /* this is a workaround to save value of right into wreg too,
12471 * value of wreg is going to be used later */
12472 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12473 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12474 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12478 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12484 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12485 if(AOP_TYPE(right) == AOP_LIT) {
12487 if(know_W != (lit&0xff))
12488 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12490 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12492 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12496 } else if (AOP_TYPE(right) == AOP_CRY) {
12497 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12499 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12500 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12501 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12503 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12504 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12505 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12507 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12509 if(!_G.resDirect) /* use this aopForSym feature */
12510 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12517 pic16_freeAsmop (right,NULL,ic,FALSE);
12518 pic16_freeAsmop (result,NULL,ic,TRUE);
12521 /*-----------------------------------------------------------------*/
12522 /* genJumpTab - generates code for jump table */
12523 /*-----------------------------------------------------------------*/
12524 static void genJumpTab (iCode *ic)
12529 pCodeOp *jt_offs_hi;
12534 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12535 /* get the condition into accumulator */
12536 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12538 /* multiply by three */
12539 pic16_emitcode("add","a,acc");
12540 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12542 jtab = newiTempLabel(NULL);
12543 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12544 pic16_emitcode("jmp","@a+dptr");
12545 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12548 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12549 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12551 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12552 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12553 pic16_emitpLabel(jtab->key);
12557 jt_offs = pic16_popGetTempReg(0);
12558 jt_offs_hi = pic16_popGetTempReg(1);
12559 jt_label = pic16_popGetLabel (jtab->key);
12560 //fprintf (stderr, "Creating jump table...\n");
12562 // calculate offset into jump table (idx * sizeof (GOTO))
12563 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12564 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12565 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12566 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12567 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12568 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12569 pic16_emitpcode(POC_MOVWF , jt_offs);
12571 // prepare PCLATx (set to first entry in jump table)
12572 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12573 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12574 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12575 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12576 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12578 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12579 pic16_emitpcode(POC_ADDWF , jt_offs);
12580 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12581 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12583 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12585 // release temporaries and prepare jump into table (new PCL --> WREG)
12586 pic16_emitpcode(POC_MOVFW , jt_offs);
12587 pic16_popReleaseTempReg (jt_offs_hi, 1);
12588 pic16_popReleaseTempReg (jt_offs, 0);
12590 // jump into the table
12591 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12593 pic16_emitpLabelFORCE(jtab->key);
12596 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12597 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12599 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12600 /* now generate the jump labels */
12601 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12602 jtab = setNextItem(IC_JTLABELS(ic))) {
12603 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12604 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12607 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12611 /*-----------------------------------------------------------------*/
12612 /* genMixedOperation - gen code for operators between mixed types */
12613 /*-----------------------------------------------------------------*/
12615 TSD - Written for the PIC port - but this unfortunately is buggy.
12616 This routine is good in that it is able to efficiently promote
12617 types to different (larger) sizes. Unfortunately, the temporary
12618 variables that are optimized out by this routine are sometimes
12619 used in other places. So until I know how to really parse the
12620 iCode tree, I'm going to not be using this routine :(.
12622 static int genMixedOperation (iCode *ic)
12625 operand *result = IC_RESULT(ic);
12626 sym_link *ctype = operandType(IC_LEFT(ic));
12627 operand *right = IC_RIGHT(ic);
12633 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12635 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12641 nextright = IC_RIGHT(nextic);
12642 nextleft = IC_LEFT(nextic);
12643 nextresult = IC_RESULT(nextic);
12645 pic16_aopOp(right,ic,FALSE);
12646 pic16_aopOp(result,ic,FALSE);
12647 pic16_aopOp(nextright, nextic, FALSE);
12648 pic16_aopOp(nextleft, nextic, FALSE);
12649 pic16_aopOp(nextresult, nextic, FALSE);
12651 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12653 operand *t = right;
12657 pic16_emitcode(";remove right +","");
12659 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12661 operand *t = right;
12665 pic16_emitcode(";remove left +","");
12669 big = AOP_SIZE(nextleft);
12670 small = AOP_SIZE(nextright);
12672 switch(nextic->op) {
12675 pic16_emitcode(";optimize a +","");
12676 /* if unsigned or not an integral type */
12677 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12678 pic16_emitcode(";add a bit to something","");
12681 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12683 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12684 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12685 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12687 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12695 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12696 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12697 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12700 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12702 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12703 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12704 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12705 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12706 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12709 pic16_emitcode("rlf","known_zero,w");
12716 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12717 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12718 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12720 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12730 pic16_freeAsmop(right,NULL,ic,TRUE);
12731 pic16_freeAsmop(result,NULL,ic,TRUE);
12732 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12733 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12735 nextic->generated = 1;
12742 /*-----------------------------------------------------------------*/
12743 /* genCast - gen code for casting */
12744 /*-----------------------------------------------------------------*/
12745 static void genCast (iCode *ic)
12747 operand *result = IC_RESULT(ic);
12748 sym_link *ctype = operandType(IC_LEFT(ic));
12749 sym_link *rtype = operandType(IC_RIGHT(ic));
12750 sym_link *restype = operandType(IC_RESULT(ic));
12751 operand *right = IC_RIGHT(ic);
12757 /* if they are equivalent then do nothing */
12758 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12761 pic16_aopOp(result,ic,FALSE);
12762 pic16_aopOp(right,ic,FALSE) ;
12764 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12767 /* if the result is a bit */
12768 if (AOP_TYPE(result) == AOP_CRY) {
12770 /* if the right size is a literal then
12771 * we know what the value is */
12772 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12774 if (AOP_TYPE(right) == AOP_LIT) {
12775 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12776 pic16_popGet(AOP(result),0));
12778 if (((int) operandLitValue(right)))
12779 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12780 AOP(result)->aopu.aop_dir,
12781 AOP(result)->aopu.aop_dir);
12783 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12784 AOP(result)->aopu.aop_dir,
12785 AOP(result)->aopu.aop_dir);
12789 /* the right is also a bit variable */
12790 if (AOP_TYPE(right) == AOP_CRY) {
12792 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12794 pic16_emitcode("clrc","");
12795 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12796 AOP(right)->aopu.aop_dir,
12797 AOP(right)->aopu.aop_dir);
12798 pic16_aopPut(AOP(result),"c",0);
12802 /* we need to or */
12803 if (AOP_TYPE(right) == AOP_REG) {
12804 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12805 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12806 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12808 pic16_toBoolean(right);
12809 pic16_aopPut(AOP(result),"a",0);
12813 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12816 size = AOP_SIZE(result);
12818 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12820 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12821 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12822 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12825 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12830 if(IS_BITFIELD(getSpec(restype))
12831 && IS_BITFIELD(getSpec(rtype))) {
12832 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12835 /* if they are the same size : or less */
12836 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12838 /* if they are in the same place */
12839 if (pic16_sameRegs(AOP(right),AOP(result)))
12842 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12844 if (IS_PTR_CONST(rtype))
12846 if (IS_CODEPTR(rtype))
12848 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12851 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12853 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12855 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12858 if(AOP_TYPE(right) == AOP_IMMD) {
12859 pCodeOp *pcop0, *pcop1, *pcop2;
12860 symbol *sym = OP_SYMBOL( right );
12862 size = AOP_SIZE(result);
12864 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12866 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12868 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12871 pic16_emitpcode(POC_MOVLW, pcop0);
12872 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12873 pic16_emitpcode(POC_MOVLW, pcop1);
12874 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12875 pic16_emitpcode(POC_MOVLW, pcop2);
12876 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12879 pic16_emitpcode(POC_MOVLW, pcop0);
12880 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12881 pic16_emitpcode(POC_MOVLW, pcop1);
12882 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12884 pic16_emitpcode(POC_MOVLW, pcop0);
12885 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12889 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12890 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12891 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12892 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12893 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12894 if(AOP_SIZE(result) <2)
12895 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12897 /* if they in different places then copy */
12898 size = AOP_SIZE(result);
12901 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12902 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12909 /* if the result is of type pointer */
12910 if (IS_PTR(ctype)) {
12912 sym_link *type = operandType(right);
12913 sym_link *etype = getSpec(type);
12915 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12917 /* pointer to generic pointer */
12918 if (IS_GENPTR(ctype)) {
12922 p_type = DCL_TYPE(type);
12924 /* we have to go by the storage class */
12925 p_type = PTR_TYPE(SPEC_OCLS(etype));
12927 /* if (SPEC_OCLS(etype)->codesp ) */
12928 /* p_type = CPOINTER ; */
12930 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12931 /* p_type = FPOINTER ; */
12933 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12934 /* p_type = PPOINTER; */
12936 /* if (SPEC_OCLS(etype) == idata ) */
12937 /* p_type = IPOINTER ; */
12939 /* p_type = POINTER ; */
12942 /* the first two bytes are known */
12943 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
12944 size = GPTRSIZE - 1;
12947 if(offset < AOP_SIZE(right)) {
12948 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12949 pic16_mov2f(AOP(result), AOP(right), offset);
12951 if ((AOP_TYPE(right) == AOP_PCODE) &&
12952 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12953 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12954 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12957 pic16_aopPut(AOP(result),
12958 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12963 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12966 /* the last byte depending on type */
12970 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12971 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12972 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12976 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12980 pic16_emitcode(";BUG!? ","%d",__LINE__);
12984 pic16_emitcode(";BUG!? ","%d",__LINE__);
12989 if (GPTRSIZE > AOP_SIZE(right)) {
12990 // assume data pointer... THIS MIGHT BE WRONG!
12991 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12992 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12994 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12999 /* this should never happen */
13000 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13001 "got unknown pointer type");
13004 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13010 /* just copy the pointers */
13011 size = AOP_SIZE(result);
13014 pic16_aopPut(AOP(result),
13015 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13024 /* so we now know that the size of destination is greater
13025 than the size of the source.
13026 Now, if the next iCode is an operator then we might be
13027 able to optimize the operation without performing a cast.
13029 if(genMixedOperation(ic))
13032 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13034 /* we move to result for the size of source */
13035 size = AOP_SIZE(right);
13040 pic16_mov2f(AOP(result), AOP(right), offset);
13044 /* now depending on the sign of the destination */
13045 size = AOP_SIZE(result) - AOP_SIZE(right);
13046 /* if unsigned or not an integral type */
13047 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13049 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13051 /* we need to extend the sign :( */
13054 /* Save one instruction of casting char to int */
13055 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13056 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13057 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13059 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13062 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13064 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13066 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13069 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13074 pic16_freeAsmop(right,NULL,ic,TRUE);
13075 pic16_freeAsmop(result,NULL,ic,TRUE);
13079 /*-----------------------------------------------------------------*/
13080 /* genDjnz - generate decrement & jump if not zero instrucion */
13081 /*-----------------------------------------------------------------*/
13082 static int genDjnz (iCode *ic, iCode *ifx)
13084 symbol *lbl, *lbl1;
13085 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13090 /* if the if condition has a false label
13091 then we cannot save */
13095 /* if the minus is not of the form
13097 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13098 !IS_OP_LITERAL(IC_RIGHT(ic)))
13101 if (operandLitValue(IC_RIGHT(ic)) != 1)
13104 /* if the size of this greater than one then no
13106 if (getSize(operandType(IC_RESULT(ic))) > 1)
13109 /* otherwise we can save BIG */
13110 lbl = newiTempLabel(NULL);
13111 lbl1= newiTempLabel(NULL);
13113 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13115 if (IS_AOP_PREG(IC_RESULT(ic))) {
13116 pic16_emitcode("dec","%s",
13117 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13118 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13119 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13123 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13124 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13126 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13127 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13131 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13132 ifx->generated = 1;
13136 /*-----------------------------------------------------------------*/
13137 /* genReceive - generate code for a receive iCode */
13138 /*-----------------------------------------------------------------*/
13139 static void genReceive (iCode *ic)
13145 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13146 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13148 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13150 if (isOperandInFarSpace(IC_RESULT(ic))
13151 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13152 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13154 int size = getSize(operandType(IC_RESULT(ic)));
13155 int offset = pic16_fReturnSizePic - size;
13159 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13160 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13164 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13166 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13167 size = AOP_SIZE(IC_RESULT(ic));
13170 pic16_emitcode ("pop","acc");
13171 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13174 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13176 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13179 /* set pseudo stack pointer to where it should be - dw*/
13180 GpsuedoStkPtr = ic->parmBytes;
13182 /* setting GpsuedoStkPtr has side effects here: */
13183 assignResultValue(IC_RESULT(ic), 0);
13186 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13189 /*-----------------------------------------------------------------*/
13190 /* genDummyRead - generate code for dummy read of volatiles */
13191 /*-----------------------------------------------------------------*/
13193 genDummyRead (iCode * ic)
13199 if (op && IS_SYMOP(op)) {
13200 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13201 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13204 pic16_aopOp (op, ic, FALSE);
13205 for (i=0; i < AOP_SIZE(op); i++) {
13206 // may need to protect this from the peepholer -- this is not nice but works...
13207 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13208 pic16_mov2w (AOP(op),i);
13209 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13211 pic16_freeAsmop (op, NULL, ic, TRUE);
13213 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13217 /*-----------------------------------------------------------------*/
13218 /* genpic16Code - generate code for pic16 based controllers */
13219 /*-----------------------------------------------------------------*/
13221 * At this point, ralloc.c has gone through the iCode and attempted
13222 * to optimize in a way suitable for a PIC. Now we've got to generate
13223 * PIC instructions that correspond to the iCode.
13225 * Once the instructions are generated, we'll pass through both the
13226 * peep hole optimizer and the pCode optimizer.
13227 *-----------------------------------------------------------------*/
13229 void genpic16Code (iCode *lic)
13234 lineHead = lineCurr = NULL;
13236 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13237 pic16_addpBlock(pb);
13240 /* if debug information required */
13241 if (options.debug && currFunc) {
13243 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13248 for (ic = lic ; ic ; ic = ic->next ) {
13250 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13251 if ( cln != ic->lineno ) {
13252 if ( options.debug ) {
13253 debugFile->writeCLine (ic);
13256 if(!options.noCcodeInAsm) {
13257 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13258 printCLine(ic->filename, ic->lineno)));
13264 if(options.iCodeInAsm) {
13267 /* insert here code to print iCode as comment */
13268 l = Safe_strdup(printILine(ic));
13269 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13272 /* if the result is marked as
13273 * spilt and rematerializable or code for
13274 * this has already been generated then
13276 if (resultRemat(ic) || ic->generated )
13279 /* depending on the operation */
13298 /* IPOP happens only when trying to restore a
13299 * spilt live range, if there is an ifx statement
13300 * following this pop then the if statement might
13301 * be using some of the registers being popped which
13302 * would destroy the contents of the register so
13303 * we need to check for this condition and handle it */
13305 && ic->next->op == IFX
13306 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13307 genIfx (ic->next,ic);
13325 genEndFunction (ic);
13341 pic16_genPlus (ic) ;
13345 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13346 pic16_genMinus (ic);
13362 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13366 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13372 /* note these two are xlated by algebraic equivalence
13373 * during parsing SDCC.y */
13374 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13375 "got '>=' or '<=' shouldn't have come here");
13379 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13391 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13395 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13399 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13423 genRightShift (ic);
13426 case GET_VALUE_AT_ADDRESS:
13431 if (POINTER_SET(ic))
13458 addSet(&_G.sendSet,ic);
13461 case DUMMY_READ_VOLATILE:
13471 /* now we are ready to call the
13472 peep hole optimizer */
13473 if (!options.nopeep)
13474 peepHole (&lineHead);
13476 /* now do the actual printing */
13477 printLine (lineHead, codeOutFile);
13480 DFPRINTF((stderr,"printing pBlock\n\n"));
13481 pic16_printpBlock(stdout,pb);