1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic16
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
8 PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002)
9 - Vangelis Rokas vrokas@otenet.gr (2003,2004,2005)
10 Bug Fixes - Raphael Neider rneider@web.de (2004,2005)
12 This program is free software; you can redistribute it and/or modify it
13 under the terms of the GNU General Public License as published by the
14 Free Software Foundation; either version 2, or (at your option) any
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 In other words, you are welcome to use, share and improve this program.
27 You are forbidden to forbid anyone else to use, share and improve
28 what you give them. Help stamp out software-hoarding!
31 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
32 Made everything static
33 -------------------------------------------------------------------------*/
39 #include "SDCCglobl.h"
43 #include "SDCCpeeph.h"
51 /* Set the following to 1 to enable the slower/bigger
52 * but more robust generic shifting routine (which also
53 * operates correctly with negative shift values). */
54 #define USE_GENERIC_SIGNED_SHIFT 1
56 /* Set the following to 1 to enable the new
57 * stripped down genCmp version.
58 * This version should be easier to understand,
59 * more reliable and (sigh) slighly slower. */
60 #define USE_SIMPLE_GENCMP 1
62 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
63 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
64 void pic16_genMult8X8_8 (operand *, operand *,operand *);
65 void pic16_genMult16X16_16(operand *, operand *, operand *);
66 void pic16_genMult32X32_32(operand *, operand *, operand *);
67 pCode *pic16_AssembleLine(char *line, int peeps);
68 extern void pic16_printpBlock(FILE *of, pBlock *pb);
69 static asmop *newAsmop (short type);
70 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
71 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
72 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
73 static pCodeOp *pic16_popRegFromIdx(int rIdx);
75 //static int aopIdx (asmop *aop, int offset);
77 int pic16_labelOffset=0;
78 extern int pic16_debug_verbose;
79 #if !(USE_GENERIC_SIGNED_SHIFT)
80 static int optimized_for_speed = 0;
89 /* max_key keeps track of the largest label number used in
90 a function. This is then used to adjust the label offset
91 for the next function.
94 static int GpsuedoStkPtr=0;
96 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
98 unsigned int pic16aopLiteral (value *val, int offset);
99 const char *pic16_AopType(short type);
100 static iCode *ifxForOp ( operand *op, iCode *ic );
102 void pic16_pushpCodeOp(pCodeOp *pcop);
103 void pic16_poppCodeOp(pCodeOp *pcop);
105 static bool is_LitOp(operand *op);
106 static bool is_LitAOp(asmop *aop);
109 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
111 /* set the following macro to 1 to enable passing the
112 * first byte of functions parameters via WREG */
113 #define USE_WREG_IN_FUNC_PARAMS 0
116 /* this is the down and dirty file with all kinds of
117 kludgy & hacky stuff. This is what it is all about
118 CODE GENERATION for a specific MCU . some of the
119 routines may be reusable, will have to see */
121 static char *zero = "#0x00";
122 static char *one = "#0x01";
123 //static char *spname = "sp";
127 * Function return value policy (MSB-->LSB):
129 * 16 bits -> PRODL:WREG
130 * 24 bits -> PRODH:PRODL:WREG
131 * 32 bits -> FSR0L:PRODH:PRODL:WREG
132 * >32 bits -> on stack, and FSR0 points to the beginning
137 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
138 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
139 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
140 static char **fReturn = fReturnpic16;
142 static char *accUse[] = {"WREG"};
144 //static short rbank = -1;
158 bitVect *fregsUsed; /* registers used in function */
160 set *sregsAllocSet; /* registers used to store stack variables */
161 int stack_lat; /* stack offset latency */
163 int useWreg; /* flag when WREG is used to pass function parameter */
166 extern int pic16_ptrRegReq ;
167 extern int pic16_nRegs;
168 extern FILE *codeOutFile;
169 //static void saverbank (int, iCode *,bool);
171 static lineNode *lineHead = NULL;
172 static lineNode *lineCurr = NULL;
174 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
175 0xE0, 0xC0, 0x80, 0x00};
176 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
177 0x07, 0x03, 0x01, 0x00};
181 /*-----------------------------------------------------------------*/
182 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
183 /* exponent of 2 is returned, otherwise -1 is */
185 /* note that this is similar to the function `powof2' in SDCCsymt */
189 /*-----------------------------------------------------------------*/
190 int pic16_my_powof2 (unsigned long num)
193 if( (num & (num-1)) == 0) {
206 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
208 DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
210 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
211 ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
212 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
213 ((left) ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
214 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
215 ((right) ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
216 ((result) ? AOP_SIZE(result) : 0));
219 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
222 DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
224 ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
225 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
226 ((left) ? pic16_AopType(AOP_TYPE(left)) : "-"),
227 ((left) ? (SPEC_USIGN(operandType(left)) ? 'u' : 's') : '-'),
228 ((right) ? pic16_AopType(AOP_TYPE(right)) : "-"),
229 ((right) ? (SPEC_USIGN(operandType(right)) ? 'u' : 's') : '-'));
233 void pic16_emitpcomment (char *fmt, ...)
236 char lb[INITIAL_INLINEASM];
242 vsprintf(lb+1,fmt,ap);
244 while (isspace(*lbp)) lbp++;
247 lineCurr = (lineCurr ?
248 connectLine(lineCurr,newLineNode(lb)) :
249 (lineHead = newLineNode(lb)));
250 lineCurr->isInline = _G.inLine;
251 lineCurr->isDebug = _G.debugLine;
253 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
256 // fprintf(stderr, "%s\n", lb);
259 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
262 char lb[INITIAL_INLINEASM];
265 if(!pic16_debug_verbose)
272 sprintf(lb,"%s\t",inst);
274 sprintf(lb,"%s",inst);
275 vsprintf(lb+(strlen(lb)),fmt,ap);
279 while (isspace(*lbp)) lbp++;
282 lineCurr = (lineCurr ?
283 connectLine(lineCurr,newLineNode(lb)) :
284 (lineHead = newLineNode(lb)));
285 lineCurr->isInline = _G.inLine;
286 lineCurr->isDebug = _G.debugLine;
288 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
291 // fprintf(stderr, "%s\n", lb);
296 void pic16_emitpLabel(int key)
298 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
301 void pic16_emitpLabelFORCE(int key)
303 pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
306 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
307 * NEVER call pic16_emitpcode_real directly, please... */
308 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
312 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
314 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
317 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
320 pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
322 DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
325 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
328 pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
334 #define pic16_emitcode DEBUGpic16_emitcode
336 /*-----------------------------------------------------------------*/
337 /* pic16_emitcode - writes the code into a file : for now it is simple */
338 /*-----------------------------------------------------------------*/
339 void pic16_emitcode (char *inst,char *fmt, ...)
342 char lb[INITIAL_INLINEASM];
349 sprintf(lb,"%s\t",inst);
351 sprintf(lb,"%s",inst);
352 vsprintf(lb+(strlen(lb)),fmt,ap);
356 while (isspace(*lbp)) lbp++;
359 lineCurr = (lineCurr ?
360 connectLine(lineCurr,newLineNode(lb)) :
361 (lineHead = newLineNode(lb)));
362 lineCurr->isInline = _G.inLine;
363 lineCurr->isDebug = _G.debugLine;
365 // VR fprintf(stderr, "lb = <%s>\n", lbp);
367 // if(pic16_debug_verbose)
368 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
375 /*-----------------------------------------------------------------*/
376 /* pic16_emitDebuggerSymbol - associate the current code location */
377 /* with a debugger symbol */
378 /*-----------------------------------------------------------------*/
380 pic16_emitDebuggerSymbol (char * debugSym)
383 pic16_emitcode (";", "%s ==.", debugSym);
388 /*-----------------------------------------------------------------*/
389 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
390 /*-----------------------------------------------------------------*/
391 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
393 // bool r0iu = FALSE , r1iu = FALSE;
394 // bool r0ou = FALSE , r1ou = FALSE;
395 bool fsr0iu = FALSE, fsr0ou;
396 bool fsr2iu = FALSE, fsr2ou;
398 fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
401 fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
402 fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
404 fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
405 fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
407 if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
408 fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
409 DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
412 if(!fsr0iu && !fsr0ou) {
413 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
414 (*aopp)->type = AOP_FSR0;
416 fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
418 return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
422 /* no usage of FSR2 */
423 if(!fsr2iu && !fsr2ou) {
424 ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
425 (*aopp)->type = AOP_FSR2;
427 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
431 /* now we know they both have usage */
432 /* if fsr0 not used in this instruction */
434 if (!_G.fsr0Pushed) {
435 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
436 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
440 ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
441 (*aopp)->type = AOP_FSR0;
443 // fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
445 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
449 fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
454 /* the logic: if r0 & r1 used in the instruction
455 then we are in trouble otherwise */
457 /* first check if r0 & r1 are used by this
458 instruction, in which case we are in trouble */
459 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
460 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
465 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
466 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
468 /* if no usage of r0 then return it */
469 if (!r0iu && !r0ou) {
470 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
471 (*aopp)->type = AOP_R0;
473 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
476 /* if no usage of r1 then return it */
477 if (!r1iu && !r1ou) {
478 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
479 (*aopp)->type = AOP_R1;
481 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
484 /* now we know they both have usage */
485 /* if r0 not used in this instruction */
487 /* push it if not already pushed */
489 //pic16_emitcode ("push","%s",
490 // pic16_regWithIdx(R0_IDX)->dname);
494 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
495 (*aopp)->type = AOP_R0;
497 return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
500 /* if r1 not used then */
503 /* push it if not already pushed */
505 //pic16_emitcode ("push","%s",
506 // pic16_regWithIdx(R1_IDX)->dname);
510 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
511 (*aopp)->type = AOP_R1;
512 return pic16_regWithIdx(R1_IDX);
516 /* I said end of world but not quite end of world yet */
517 /* if this is a result then we can push it on the stack*/
519 (*aopp)->type = AOP_STK;
523 /* other wise this is true end of the world */
524 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
525 "getFreePtr should never reach here");
530 /*-----------------------------------------------------------------*/
531 /* newAsmop - creates a new asmOp */
532 /*-----------------------------------------------------------------*/
533 static asmop *newAsmop (short type)
537 aop = Safe_calloc(1,sizeof(asmop));
542 static void genSetDPTR(int n)
546 pic16_emitcode(";", "Select standard DPTR");
547 pic16_emitcode("mov", "dps, #0x00");
551 pic16_emitcode(";", "Select alternate DPTR");
552 pic16_emitcode("mov", "dps, #0x01");
556 /*-----------------------------------------------------------------*/
557 /* resolveIfx - converts an iCode ifx into a form more useful for */
558 /* generating code */
559 /*-----------------------------------------------------------------*/
560 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
564 // DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
570 resIfx->condition = 1; /* assume that the ifx is true */
571 resIfx->generated = 0; /* indicate that the ifx has not been used */
574 resIfx->lbl = newiTempLabel(NULL); /* oops, there is no ifx. so create a label */
577 DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
578 __FUNCTION__,__LINE__,resIfx->lbl->key);
583 resIfx->lbl = IC_TRUE(ifx);
585 resIfx->lbl = IC_FALSE(ifx);
586 resIfx->condition = 0;
591 DEBUGpic16_emitcode("; +++","ifx true is non-null");
593 DEBUGpic16_emitcode("; +++","ifx true is null");
595 DEBUGpic16_emitcode("; +++","ifx false is non-null");
597 DEBUGpic16_emitcode("; +++","ifx false is null");
601 DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
605 /*-----------------------------------------------------------------*/
606 /* pointerCode - returns the code for a pointer type */
607 /*-----------------------------------------------------------------*/
608 static int pointerCode (sym_link *etype)
611 return PTR_TYPE(SPEC_OCLS(etype));
616 /*-----------------------------------------------------------------*/
617 /* aopForSym - for a true symbol */
618 /*-----------------------------------------------------------------*/
619 static asmop *aopForSym (iCode *ic, operand *op, bool result)
621 symbol *sym=OP_SYMBOL(op);
623 memmap *space= SPEC_OCLS(sym->etype);
627 _G.resDirect = 0; /* clear flag that instructs the result is loaded directly from aopForSym */
629 // sym = OP_SYMBOL(op);
631 /* if already has one */
633 DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
638 /* if symbol was initially placed onStack then we must re-place it
639 * to direct memory, since pic16 does not have a specific stack */
641 fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
649 fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
651 sym->aop = aop = newAsmop (AOP_PAGED);
652 aop->aopu.aop_dir = sym->rname ;
653 aop->size = getSize(sym->type);
654 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
655 pic16_allocDirReg( IC_LEFT(ic) );
663 /* assign depending on the storage class */
664 /* if it is on the stack or indirectly addressable */
665 /* space we need to assign either r0 or r1 to it */
666 if (sym->onStack) // || sym->iaccess)
671 DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
672 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
674 /* acquire a temporary register -- it is saved in function */
676 sym->aop = aop = newAsmop(AOP_STA);
677 aop->aopu.stk.stk = sym->stack;
678 aop->size = getSize(sym->type);
681 DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
682 if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
683 && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
684 // pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
686 for(i=0;i<aop->size;i++)
687 aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
688 _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */
690 if(1 && ic->op == SEND) {
692 /* if SEND do the send here */
695 for(i=0;i<aop->size;i++) {
696 aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
697 _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
702 // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
705 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
707 // we do not need to load the value if it is to be defined...
708 if (result) return aop;
711 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
714 for(i=0;i<aop->size;i++) {
716 /* initialise for stack access via frame pointer */
717 // operands on stack are accessible via "FSR2 + index" with index
718 // starting at 2 for arguments and growing from 0 downwards for
719 // local variables (index == 0 is not assigned so we add one here)
721 int soffs = sym->stack;
727 if(1 && ic->op == SEND) {
728 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
729 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
730 pic16_popCopyReg( pic16_frame_plusw ),
731 pic16_popCopyReg(pic16_stack_postdec )));
733 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
734 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
735 pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
741 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
748 /* now assign the address of the variable to
749 the pointer register */
750 if (aop->type != AOP_STK) {
754 pic16_emitcode("push","acc");
756 pic16_emitcode("mov","a,_bp");
757 pic16_emitcode("add","a,#0x%02x",
759 ((char)(sym->stack - _G.nRegsSaved )) :
760 ((char)sym->stack)) & 0xff);
761 pic16_emitcode("mov","%s,a",
762 aop->aopu.aop_ptr->name);
765 pic16_emitcode("pop","acc");
767 pic16_emitcode("mov","%s,#%s",
768 aop->aopu.aop_ptr->name,
770 aop->paged = space->paged;
772 aop->aopu.aop_stk = sym->stack;
780 if (sym->onStack && options.stack10bit)
782 /* It's on the 10 bit stack, which is located in
786 //DEBUGpic16_emitcode(";","%d",__LINE__);
789 pic16_emitcode("push","acc");
791 pic16_emitcode("mov","a,_bp");
792 pic16_emitcode("add","a,#0x%02x",
794 ((char)(sym->stack - _G.nRegsSaved )) :
795 ((char)sym->stack)) & 0xff);
798 pic16_emitcode ("mov","dpx1,#0x40");
799 pic16_emitcode ("mov","dph1,#0x00");
800 pic16_emitcode ("mov","dpl1, a");
804 pic16_emitcode("pop","acc");
806 sym->aop = aop = newAsmop(AOP_DPTR2);
807 aop->size = getSize(sym->type);
813 /* special case for a function */
814 if (IS_FUNC(sym->type)) {
815 sym->aop = aop = newAsmop(AOP_PCODE);
816 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
817 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
818 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
819 PCOI(aop->aopu.pcop)->index = 0;
820 aop->size = FPTRSIZE;
821 DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
828 //DEBUGpic16_emitcode(";","%d",__LINE__);
829 /* if in bit space */
830 if (IN_BITSPACE(space)) {
831 sym->aop = aop = newAsmop (AOP_CRY);
832 aop->aopu.aop_dir = sym->rname ;
833 aop->size = getSize(sym->type);
834 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
837 /* if it is in direct space */
838 if (IN_DIRSPACE(space)) {
839 sym->aop = aop = newAsmop (AOP_DIR);
840 aop->aopu.aop_dir = sym->rname ;
841 aop->size = getSize(sym->type);
842 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
843 pic16_allocDirReg( IC_LEFT(ic) );
848 if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
849 sym->aop = aop = newAsmop (AOP_DIR);
850 aop->aopu.aop_dir = sym->rname ;
851 aop->size = getSize(sym->type);
852 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
853 pic16_allocDirReg( IC_LEFT(ic) );
858 /* only remaining is far space */
859 sym->aop = aop = newAsmop(AOP_PCODE);
861 /* change the next if to 1 to revert to good old immediate code */
862 if(IN_CODESPACE(space)) {
863 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
864 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
865 PCOI(aop->aopu.pcop)->index = 0;
867 /* try to allocate via direct register */
868 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
869 // aop->size = getSize( sym->type );
872 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
873 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
876 if(!pic16_allocDirReg (IC_LEFT(ic)))
880 if(IN_DIRSPACE( space ))
882 else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
883 aop->size = FPTRSIZE;
884 else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
885 else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
886 else if(sym->onStack) {
889 if(SPEC_SCLS(sym->etype) == S_PDATA) {
890 fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
891 aop->size = FPTRSIZE;
896 DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
898 /* if it is in code space */
899 if (IN_CODESPACE(space))
905 /*-----------------------------------------------------------------*/
906 /* aopForRemat - rematerialzes an object */
907 /*-----------------------------------------------------------------*/
908 static asmop *aopForRemat (operand *op) // x symbol *sym)
910 symbol *sym = OP_SYMBOL(op);
912 iCode *ic = NULL, *oldic;
913 asmop *aop = newAsmop(AOP_PCODE);
920 ic = sym->rematiCode;
922 if(IS_OP_POINTER(op)) {
923 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
929 // pic16_emitpcomment("ic: %s\n", printILine(ic));
932 val += (int) operandLitValue(IC_RIGHT(ic));
933 } else if (ic->op == '-') {
934 val -= (int) operandLitValue(IC_RIGHT(ic));
938 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
941 offset = OP_SYMBOL(IC_LEFT(ic))->offset;
944 if(!op->isaddr)viaimmd++; else viaimmd=0;
946 /* set the following if to 1 to revert to good old immediate code */
947 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
950 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
952 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
955 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
957 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
960 PCOI(aop->aopu.pcop)->index = val;
962 aop->size = getSize( sym->type );
964 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize( OP_SYMBOL( IC_LEFT(ic))->type));
966 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
967 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
969 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
973 DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
974 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
976 val, IS_PTR_CONST(operandType(op)));
978 val, IS_CODEPTR(operandType(op)));
981 // DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
983 pic16_allocDirReg (IC_LEFT(ic));
985 if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
992 static int aopIdx (asmop *aop, int offset)
997 if(aop->type != AOP_REG)
1000 return aop->aopu.aop_reg[offset]->rIdx;
1005 /*-----------------------------------------------------------------*/
1006 /* regsInCommon - two operands have some registers in common */
1007 /*-----------------------------------------------------------------*/
1008 static bool regsInCommon (operand *op1, operand *op2)
1010 symbol *sym1, *sym2;
1013 /* if they have registers in common */
1014 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1017 sym1 = OP_SYMBOL(op1);
1018 sym2 = OP_SYMBOL(op2);
1020 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1023 for (i = 0 ; i < sym1->nRegs ; i++) {
1028 for (j = 0 ; j < sym2->nRegs ;j++ ) {
1032 if (sym2->regs[j] == sym1->regs[i])
1040 /*-----------------------------------------------------------------*/
1041 /* operandsEqu - equivalent */
1042 /*-----------------------------------------------------------------*/
1043 static bool operandsEqu ( operand *op1, operand *op2)
1045 symbol *sym1, *sym2;
1047 /* if they not symbols */
1048 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1051 sym1 = OP_SYMBOL(op1);
1052 sym2 = OP_SYMBOL(op2);
1054 /* if both are itemps & one is spilt
1055 and the other is not then false */
1056 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1057 sym1->isspilt != sym2->isspilt )
1060 /* if they are the same */
1064 if (sym1->rname[0] && sym2->rname[0]
1065 && strcmp (sym1->rname, sym2->rname) == 0)
1069 /* if left is a tmp & right is not */
1070 if (IS_ITEMP(op1) &&
1073 (sym1->usl.spillLoc == sym2))
1076 if (IS_ITEMP(op2) &&
1080 (sym2->usl.spillLoc == sym1))
1086 /*-----------------------------------------------------------------*/
1087 /* pic16_sameRegs - two asmops have the same registers */
1088 /*-----------------------------------------------------------------*/
1089 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1096 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1097 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1099 if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1101 if (aop1->type != AOP_REG ||
1102 aop2->type != AOP_REG )
1105 /* This is a bit too restrictive if one is a subset of the other...
1106 if (aop1->size != aop2->size )
1110 for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1111 // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1113 // if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1114 if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1121 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1123 DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1124 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1126 if(aop1 == aop2)return TRUE;
1127 if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1129 if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1135 /*-----------------------------------------------------------------*/
1136 /* pic16_aopOp - allocates an asmop for an operand : */
1137 /*-----------------------------------------------------------------*/
1138 void pic16_aopOp (operand *op, iCode *ic, bool result)
1147 DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1149 /* if this a literal */
1150 if (IS_OP_LITERAL(op)) {
1151 op->aop = aop = newAsmop(AOP_LIT);
1152 aop->aopu.aop_lit = op->operand.valOperand;
1153 aop->size = getSize(operandType(op));
1158 sym_link *type = operandType(op);
1160 if(IS_PTR_CONST(type))
1162 if(IS_CODEPTR(type))
1164 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1167 /* if already has a asmop then continue */
1171 /* if the underlying symbol has a aop */
1172 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1173 DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1174 op->aop = OP_SYMBOL(op)->aop;
1178 /* if this is a true symbol */
1179 if (IS_TRUE_SYMOP(op)) {
1180 DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1181 op->aop = aopForSym(ic, op, result);
1185 /* this is a temporary : this has
1191 e) can be a return use only */
1193 sym = OP_SYMBOL(op);
1195 DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1196 /* if the type is a conditional */
1197 if (sym->regType == REG_CND) {
1198 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1203 /* if it is spilt then two situations
1205 b) has a spill location */
1206 if (sym->isspilt || sym->nRegs == 0) {
1208 // debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1209 DEBUGpic16_emitcode(";","%d",__LINE__);
1210 /* rematerialize it NOW */
1213 sym->aop = op->aop = aop = aopForRemat (op);
1214 // aop->size = getSize(sym->type);
1215 // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1222 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1223 aop->size = getSize(sym->type);
1224 for ( i = 0 ; i < 1 ; i++ ) {
1225 aop->aopu.aop_str[i] = accUse[i];
1226 // aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1228 fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1229 DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1237 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1238 aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1239 //pic16_allocDirReg (IC_LEFT(ic));
1240 aop->size = getSize(sym->type);
1245 aop = op->aop = sym->aop = newAsmop(AOP_REG);
1246 aop->size = getSize(sym->type);
1247 for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1248 aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1250 DEBUGpic16_emitcode(";","%d",__LINE__);
1254 /* else spill location */
1255 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1256 /* force a new aop if sizes differ */
1257 sym->usl.spillLoc->aop = NULL;
1261 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1262 __FUNCTION__,__LINE__,
1263 sym->usl.spillLoc->rname,
1264 sym->rname, sym->usl.spillLoc->offset);
1267 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1268 //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1269 if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1270 aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1272 sym->usl.spillLoc->offset, op);
1274 fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1275 pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1276 assert (getSize(sym->type) <= 1);
1277 aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1279 aop->size = getSize(sym->type);
1285 sym_link *type = operandType(op);
1287 if(IS_PTR_CONST(type))
1289 if(IS_CODEPTR(type))
1291 DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1294 /* must be in a register */
1295 DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1296 sym->aop = op->aop = aop = newAsmop(AOP_REG);
1297 aop->size = sym->nRegs;
1298 for ( i = 0 ; i < sym->nRegs ;i++)
1299 aop->aopu.aop_reg[i] = sym->regs[i];
1302 /*-----------------------------------------------------------------*/
1303 /* pic16_freeAsmop - free up the asmop given to an operand */
1304 /*----------------------------------------------------------------*/
1305 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1322 /* depending on the asmop type only three cases need work AOP_RO
1323 , AOP_R1 && AOP_STK */
1325 switch (aop->type) {
1327 if (_G.fsr0Pushed ) {
1329 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1330 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1331 // pic16_emitcode ("pop","ar0");
1335 bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1339 bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1345 pic16_emitcode ("pop","ar0");
1349 bitVectUnSetBit(ic->rUsed,R0_IDX);
1355 pic16_emitcode ("pop","ar1");
1359 bitVectUnSetBit(ic->rUsed,R1_IDX);
1366 /* we must store the result on stack */
1367 if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1368 // operands on stack are accessible via "FSR2 + index" with index
1369 // starting at 2 for arguments and growing from 0 downwards for
1370 // local variables (index == 0 is not assigned so we add one here)
1371 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1376 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1377 for(i=0;i<aop->size;i++) {
1378 /* initialise for stack access via frame pointer */
1379 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1380 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1381 aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1384 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1388 for(i=0;i<aop->size;i++) {
1389 PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1391 if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1392 bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1403 int stk = aop->aopu.aop_stk + aop->size;
1404 bitVectUnSetBit(ic->rUsed,R0_IDX);
1405 bitVectUnSetBit(ic->rUsed,R1_IDX);
1407 getFreePtr(ic,&aop,FALSE);
1409 if (options.stack10bit)
1411 /* I'm not sure what to do here yet... */
1414 "*** Warning: probably generating bad code for "
1415 "10 bit stack mode.\n");
1419 pic16_emitcode ("mov","a,_bp");
1420 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1421 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1423 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1427 pic16_emitcode("pop","acc");
1428 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1430 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1433 pic16_freeAsmop(op,NULL,ic,TRUE);
1435 pic16_emitcode("pop","ar0");
1440 pic16_emitcode("pop","ar1");
1450 /* all other cases just dealloc */
1454 OP_SYMBOL(op)->aop = NULL;
1455 /* if the symbol has a spill */
1457 SPIL_LOC(op)->aop = NULL;
1462 /*-----------------------------------------------------------------*/
1463 /* pic16_aopGet - for fetching value of the aop */
1464 /*-----------------------------------------------------------------*/
1465 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1470 //DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1472 /* offset is greater than size then zero */
1473 if (offset > (aop->size - 1) &&
1474 aop->type != AOP_LIT)
1477 /* depending on type */
1478 switch (aop->type) {
1482 sprintf(s, "%s", aop->aopu.aop_ptr->name);
1483 rs = Safe_calloc(1, strlen(s)+1);
1488 /* if we need to increment it */
1489 while (offset > aop->coff)
1491 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1495 while (offset < aop->coff)
1497 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1503 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1504 return (dname ? "acc" : "a");
1506 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1507 rs = Safe_calloc (1, strlen (s) + 1);
1515 sprintf (s,"%s",aop->aopu.aop_immd);
1518 sprintf(s,"(%s >> %d)",
1523 aop->aopu.aop_immd);
1524 DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1525 rs = Safe_calloc(1,strlen(s)+1);
1531 sprintf(s,"(%s + %d)",
1534 DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1536 sprintf(s,"%s",aop->aopu.aop_dir);
1537 rs = Safe_calloc(1,strlen(s)+1);
1543 // return aop->aopu.aop_reg[offset]->dname;
1545 return aop->aopu.aop_reg[offset]->name;
1548 //pic16_emitcode(";","%d",__LINE__);
1549 return aop->aopu.aop_dir;
1552 DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1553 // fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1555 // return aop->aopu.aop_str[offset]; //->"AOP_accumulator_bug";
1556 rs = Safe_strdup("WREG");
1560 sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1561 rs = Safe_calloc(1,strlen(s)+1);
1566 aop->coff = offset ;
1568 // if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1571 if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1572 aop->type = AOP_ACC;
1573 return Safe_strdup("WREG");
1575 DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1577 return aop->aopu.aop_str[offset];
1581 pCodeOp *pcop = aop->aopu.pcop;
1582 DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1584 DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1585 //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1587 sprintf(s,"(%s + %d)", pcop->name, offset);
1589 sprintf(s,"%s", pcop->name);
1592 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1595 rs = Safe_calloc(1,strlen(s)+1);
1601 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1603 sprintf(s,"(%s + %d)",
1607 sprintf(s,"%s",aop->aopu.aop_dir);
1608 DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1609 rs = Safe_calloc(1,strlen(s)+1);
1615 rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1619 // pCodeOp *pcop = aop->aop
1624 fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1625 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1626 "aopget got unsupported aop->type");
1632 /* lock has the following meaning: When allocating temporary registers
1633 * for stack variables storage, the value of the temporary register is
1634 * saved on stack. Its value is restored at the end. This procedure is
1635 * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1636 * a possibility that before a call to pic16_aopOp, a temporary register
1637 * is allocated for a while and it is freed after some time, this will
1638 * mess the stack and values will not be restored properly. So use lock=1
1639 * to allocate temporary registers used internally by the programmer, and
1640 * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1641 * to inform the compiler developer about a possible bug. This is an internal
1642 * feature for developing the compiler -- VR */
1644 int _TempReg_lock = 0;
1645 /*-----------------------------------------------------------------*/
1646 /* pic16_popGetTempReg - create a new temporary pCodeOp */
1647 /*-----------------------------------------------------------------*/
1648 pCodeOp *pic16_popGetTempReg(int lock)
1653 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1655 // werror(W_POSSBUG2, __FILE__, __LINE__);
1658 _TempReg_lock += lock;
1663 pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1664 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1665 PCOR(pcop)->r->wasUsed=1;
1666 PCOR(pcop)->r->isFree=0;
1668 /* push value on stack */
1669 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1677 /*-----------------------------------------------------------------*/
1678 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which */
1679 /* is not part of f, but don't save if */
1681 /*-----------------------------------------------------------------*/
1682 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1688 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1691 // werror(W_POSSBUG2, __FILE__, __LINE__);
1694 _TempReg_lock += lock;
1699 i = bitVectFirstBit(f);
1702 /* bypass registers that are used by function */
1703 if(!bitVectBitValue(f, i)) {
1705 /* bypass registers that are already allocated for stack access */
1706 if(!bitVectBitValue(v, i)) {
1708 // debugf("getting register rIdx = %d\n", i);
1709 /* ok, get the operand */
1710 pcop = pic16_newpCodeOpReg( i );
1712 /* should never by NULL */
1713 assert( pcop != NULL );
1717 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1720 PCOR(pcop)->r->wasUsed=1;
1721 PCOR(pcop)->r->isFree=0;
1727 for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1729 if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1730 /* already used in previous steps, break */
1737 /* caller takes care of the following */
1738 // bitVectSetBit(v, i);
1741 /* push value on stack */
1742 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1743 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1759 /*-----------------------------------------------------------------*/
1760 /* pic16_popReleaseTempReg - create a new temporary pCodeOp */
1761 /*-----------------------------------------------------------------*/
1762 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1764 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1766 _TempReg_lock -= lock;
1768 if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1769 PCOR(pcop)->r->isFree = 1;
1771 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1774 /*-----------------------------------------------------------------*/
1775 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
1776 /*-----------------------------------------------------------------*/
1777 pCodeOp *pic16_popGetLabel(unsigned int key)
1780 DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1785 return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1788 /*-----------------------------------------------------------------*/
1789 /* pic16_popCopyReg - copy a pcode operator */
1790 /*-----------------------------------------------------------------*/
1791 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1795 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1796 memcpy (pcor, pc, sizeof (pCodeOpReg));
1797 pcor->r->wasUsed = 1;
1799 //pcor->pcop.type = pc->pcop.type;
1801 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1802 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1804 pcor->pcop.name = NULL;
1807 //pcor->rIdx = pc->rIdx;
1808 //pcor->r->wasUsed=1;
1809 //pcor->instance = pc->instance;
1811 // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1816 /*-----------------------------------------------------------------*/
1817 /* pic16_popGetLit - asm operator to pcode operator conversion */
1818 /*-----------------------------------------------------------------*/
1819 pCodeOp *pic16_popGetLit(int lit)
1821 return pic16_newpCodeOpLit(lit);
1824 /*-----------------------------------------------------------------*/
1825 /* pic16_popGetLit2 - asm operator to pcode operator conversion */
1826 /*-----------------------------------------------------------------*/
1827 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1829 return pic16_newpCodeOpLit2(lit, arg2);
1833 /*-----------------------------------------------------------------*/
1834 /* pic16_popGetImmd - asm operator to pcode immediate conversion */
1835 /*-----------------------------------------------------------------*/
1836 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1838 return pic16_newpCodeOpImmd(name, offset,index, 0);
1842 /*-----------------------------------------------------------------*/
1843 /* pic16_popGet - asm operator to pcode operator conversion */
1844 /*-----------------------------------------------------------------*/
1845 pCodeOp *pic16_popGetWithString(char *str)
1851 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1855 pcop = pic16_newpCodeOp(str,PO_STR);
1860 /*-----------------------------------------------------------------*/
1861 /* pic16_popRegFromString - */
1862 /*-----------------------------------------------------------------*/
1863 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1866 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1867 pcop->type = PO_DIR;
1869 DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1870 // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1875 pcop->name = Safe_calloc(1,strlen(str)+1);
1876 strcpy(pcop->name,str);
1878 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1880 PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1882 /* make sure that register doesn't exist,
1883 * and operand isn't NULL
1884 * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1885 if((PCOR(pcop)->r == NULL)
1887 && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1888 // fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1889 // __FUNCTION__, __LINE__, str, size, offset);
1891 PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1892 fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1895 PCOR(pcop)->instance = offset;
1900 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1904 // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1906 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1907 PCOR(pcop)->rIdx = rIdx;
1908 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1910 PCOR(pcop)->r->isFree = 0;
1911 PCOR(pcop)->r->wasUsed = 1;
1913 pcop->type = PCOR(pcop)->r->pc_type;
1918 /*---------------------------------------------------------------------------------*/
1919 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1921 /*---------------------------------------------------------------------------------*/
1922 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1927 pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1929 /* comment the following check, so errors to throw up */
1930 // if(!pcop2)return NULL;
1932 temp = pic16_popGet(aop_dst, offset);
1933 pcop2->pcop2 = temp;
1940 /*--------------------------------------------------------------------------------.-*/
1941 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1942 /* VR 030601 , adapted by Hans Dorn */
1943 /*--------------------------------------------------------------------------------.-*/
1944 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1948 pcop2 = (pCodeOpReg2 *)src;
1956 /*---------------------------------------------------------------------------------*/
1957 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
1958 /* movff instruction */
1959 /*---------------------------------------------------------------------------------*/
1960 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1965 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1966 pcop2->pcop2 = pic16_popCopyReg(dst);
1968 /* the pCodeOp may be already allocated */
1969 pcop2 = (pCodeOpReg2 *)(src);
1970 pcop2->pcop2 = (pCodeOp *)(dst);
1977 /*-----------------------------------------------------------------*/
1978 /* pic16_popGet - asm operator to pcode operator conversion */
1979 /*-----------------------------------------------------------------*/
1980 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1982 //char *s = buffer ;
1987 /* offset is greater than
1990 // if (offset > (aop->size - 1) &&
1991 // aop->type != AOP_LIT)
1992 // return NULL; //zero;
1994 /* depending on type */
1995 switch (aop->type) {
2001 DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2002 fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2009 pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2010 PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */
2011 PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2012 PCOR(pcop)->r->wasUsed = 1;
2013 PCOR(pcop)->r->isFree = 0;
2015 PCOR(pcop)->instance = offset;
2016 pcop->type = PCOR(pcop)->r->pc_type;
2020 DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2021 return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2024 /* pCodeOp is already allocated from aopForSym */
2025 DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2026 pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2032 int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx;
2034 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2036 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2038 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2039 PCOR(pcop)->rIdx = rIdx;
2040 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2041 PCOR(pcop)->r->wasUsed=1;
2042 PCOR(pcop)->r->isFree=0;
2044 PCOR(pcop)->instance = offset;
2045 pcop->type = PCOR(pcop)->r->pc_type;
2046 // rs = aop->aopu.aop_reg[offset]->name;
2047 // DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2051 // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2052 // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2058 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2059 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2063 DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2064 return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2070 assert (aop && aop->aopu.aop_reg[offset] != NULL);
2071 rIdx = aop->aopu.aop_reg[offset]->rIdx;
2073 DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2075 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2076 // pcop->type = PO_GPR_REGISTER;
2077 PCOR(pcop)->rIdx = rIdx;
2078 PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx);
2079 PCOR(pcop)->r->wasUsed=1;
2080 PCOR(pcop)->r->isFree=0;
2082 PCOR(pcop)->instance = offset;
2083 pcop->type = PCOR(pcop)->r->pc_type;
2085 DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2086 rs = aop->aopu.aop_reg[offset]->name;
2087 DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2092 DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2094 pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2095 PCOR(pcop)->instance = offset;
2096 PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2097 //if(PCOR(pcop)->r == NULL)
2098 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2102 DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2103 return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2106 DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2107 return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2110 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2111 PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2112 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2113 pcop->type = PCOR(pcop)->r->pc_type;
2114 pcop->name = PCOR(pcop)->r->name;
2120 DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2122 ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2123 pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2124 switch( aop->aopu.pcop->type ) {
2125 case PO_DIR: PCOR(pcop)->instance += offset; break;
2126 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2131 fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2132 assert( 0 ); /* should never reach here */;
2137 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2138 "pic16_popGet got unsupported aop->type");
2141 /*-----------------------------------------------------------------*/
2142 /* pic16_aopPut - puts a string for a aop */
2143 /*-----------------------------------------------------------------*/
2144 void pic16_aopPut (asmop *aop, char *s, int offset)
2151 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2153 if (aop->size && offset > ( aop->size - 1)) {
2154 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2155 "pic16_aopPut got offset > aop->size");
2159 /* will assign value to value */
2160 /* depending on where it is ofcourse */
2161 switch (aop->type) {
2164 sprintf(d,"(%s + %d)",
2165 aop->aopu.aop_dir,offset);
2166 fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2169 sprintf(d,"%s",aop->aopu.aop_dir);
2172 DEBUGpic16_emitcode(";","%d",__LINE__);
2174 pic16_emitcode("movf","%s,w",s);
2175 pic16_emitcode("movwf","%s",d);
2178 pic16_emitcode(";BUG!? should have this:movf","%s,w %d",s,__LINE__);
2179 if(offset >= aop->size) {
2180 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2183 pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2186 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2193 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2194 //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2197 strcmp(s,"r0") == 0 ||
2198 strcmp(s,"r1") == 0 ||
2199 strcmp(s,"r2") == 0 ||
2200 strcmp(s,"r3") == 0 ||
2201 strcmp(s,"r4") == 0 ||
2202 strcmp(s,"r5") == 0 ||
2203 strcmp(s,"r6") == 0 ||
2204 strcmp(s,"r7") == 0 )
2205 pic16_emitcode("mov","%s,%s ; %d",
2206 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2210 if(strcmp(s,"W")==0 )
2211 pic16_emitcode("movf","%s,w ; %d",s,__LINE__);
2213 pic16_emitcode("movwf","%s",
2214 aop->aopu.aop_reg[offset]->name);
2216 if(strcmp(s,zero)==0) {
2217 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2219 } else if(strcmp(s,"W")==0) {
2220 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2221 pcop->type = PO_GPR_REGISTER;
2223 PCOR(pcop)->rIdx = -1;
2224 PCOR(pcop)->r = NULL;
2226 DEBUGpic16_emitcode(";","%d",__LINE__);
2227 pcop->name = Safe_strdup(s);
2228 pic16_emitpcode(POC_MOVFW,pcop);
2229 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2230 } else if(strcmp(s,one)==0) {
2231 pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2232 pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2234 pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2242 if (aop->type == AOP_DPTR2)
2248 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2249 "pic16_aopPut writting to code space");
2253 while (offset > aop->coff) {
2255 pic16_emitcode ("inc","dptr");
2258 while (offset < aop->coff) {
2260 pic16_emitcode("lcall","__decdptr");
2265 /* if not in accumulater */
2268 pic16_emitcode ("movx","@dptr,a");
2270 if (aop->type == AOP_DPTR2)
2278 while (offset > aop->coff) {
2280 pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2282 while (offset < aop->coff) {
2284 pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2290 pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2295 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2297 if (strcmp(s,"r0") == 0 ||
2298 strcmp(s,"r1") == 0 ||
2299 strcmp(s,"r2") == 0 ||
2300 strcmp(s,"r3") == 0 ||
2301 strcmp(s,"r4") == 0 ||
2302 strcmp(s,"r5") == 0 ||
2303 strcmp(s,"r6") == 0 ||
2304 strcmp(s,"r7") == 0 ) {
2306 sprintf(buffer,"a%s",s);
2307 pic16_emitcode("mov","@%s,%s",
2308 aop->aopu.aop_ptr->name,buffer);
2310 pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2315 if (strcmp(s,"a") == 0)
2316 pic16_emitcode("push","acc");
2318 pic16_emitcode("push","%s",s);
2323 /* if bit variable */
2324 if (!aop->aopu.aop_dir) {
2325 pic16_emitcode("clr","a");
2326 pic16_emitcode("rlc","a");
2329 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2332 pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2335 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2337 lbl = newiTempLabel(NULL);
2339 if (strcmp(s,"a")) {
2342 pic16_emitcode("clr","c");
2343 pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2344 pic16_emitcode("cpl","c");
2345 pic16_emitcode("","%05d_DS_:",lbl->key+100);
2346 pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2353 if (strcmp(aop->aopu.aop_str[offset],s))
2354 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2359 if (!offset && (strcmp(s,"acc") == 0))
2362 if (strcmp(aop->aopu.aop_str[offset],s))
2363 pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2367 fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2368 // werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2369 // "pic16_aopPut got unsupported aop->type");
2375 /*-----------------------------------------------------------------*/
2376 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type */
2377 /*-----------------------------------------------------------------*/
2378 void pic16_mov2w (asmop *aop, int offset)
2380 DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset);
2383 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2385 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2388 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2390 if(is_LitAOp(src)) {
2391 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2392 pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2394 if(pic16_sameRegsOfs(src, dst, offset))return;
2395 pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2396 pic16_popGet(dst, offset)));
2400 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2402 if(is_LitAOp(src)) {
2403 pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2404 pic16_emitpcode(POC_MOVWF, dst);
2406 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2410 void pic16_testStackOverflow(void)
2412 #define GSTACK_TEST_NAME "_gstack_test"
2414 pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2419 sym = newSymbol( GSTACK_TEST_NAME , 0 );
2420 sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2421 // strcpy(sym->rname, GSTACK_TEST_NAME);
2422 checkAddSym(&externs, sym);
2427 /* push pcop into stack */
2428 void pic16_pushpCodeOp(pCodeOp *pcop)
2430 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2431 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); //&pic16_pc_postdec1)));
2432 if(pic16_options.gstack)
2433 pic16_testStackOverflow();
2437 /* pop pcop from stack */
2438 void pic16_poppCodeOp(pCodeOp *pcop)
2440 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2441 if(pic16_options.gstack)
2442 pic16_testStackOverflow();
2446 /*-----------------------------------------------------------------*/
2447 /* pushw - pushes wreg to stack */
2448 /*-----------------------------------------------------------------*/
2451 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2452 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2453 if(pic16_options.gstack)
2454 pic16_testStackOverflow();
2458 /*-----------------------------------------------------------------*/
2459 /* pushaop - pushes aop to stack */
2460 /*-----------------------------------------------------------------*/
2461 void pushaop(asmop *aop, int offset)
2463 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2465 if(is_LitAOp(aop)) {
2466 pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2467 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2469 pic16_emitpcode(POC_MOVFF,
2470 pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2473 if(pic16_options.gstack)
2474 pic16_testStackOverflow();
2477 /*-----------------------------------------------------------------*/
2478 /* popaop - pops aop from stack */
2479 /*-----------------------------------------------------------------*/
2480 void popaop(asmop *aop, int offset)
2482 DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__);
2483 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2484 if(pic16_options.gstack)
2485 pic16_testStackOverflow();
2488 void popaopidx(asmop *aop, int offset, int index)
2492 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2494 if(STACK_MODEL_LARGE)ofs++;
2496 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2497 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2498 if(pic16_options.gstack)
2499 pic16_testStackOverflow();
2502 #if !(USE_GENERIC_SIGNED_SHIFT)
2503 /*-----------------------------------------------------------------*/
2504 /* reAdjustPreg - points a register back to where it should */
2505 /*-----------------------------------------------------------------*/
2506 static void reAdjustPreg (asmop *aop)
2510 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2512 if ((size = aop->size) <= 1)
2515 switch (aop->type) {
2519 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2523 if (aop->type == AOP_DPTR2)
2529 pic16_emitcode("lcall","__decdptr");
2532 if (aop->type == AOP_DPTR2)
2544 /*-----------------------------------------------------------------*/
2545 /* opIsGptr: returns non-zero if the passed operand is */
2546 /* a generic pointer type. */
2547 /*-----------------------------------------------------------------*/
2548 static int opIsGptr(operand *op)
2550 sym_link *type = operandType(op);
2552 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2553 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2561 /*-----------------------------------------------------------------*/
2562 /* pic16_getDataSize - get the operand data size */
2563 /*-----------------------------------------------------------------*/
2564 int pic16_getDataSize(operand *op)
2566 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2569 return AOP_SIZE(op);
2571 // tsd- in the pic port, the genptr size is 1, so this code here
2572 // fails. ( in the 8051 port, the size was 4).
2575 size = AOP_SIZE(op);
2576 if (size == GPTRSIZE)
2578 sym_link *type = operandType(op);
2579 if (IS_GENPTR(type))
2581 /* generic pointer; arithmetic operations
2582 * should ignore the high byte (pointer type).
2585 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2592 /*-----------------------------------------------------------------*/
2593 /* pic16_outAcc - output Acc */
2594 /*-----------------------------------------------------------------*/
2595 void pic16_outAcc(operand *result)
2598 DEBUGpic16_emitcode ("; ***","%s %d - ",__FUNCTION__,__LINE__);
2599 DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2602 size = pic16_getDataSize(result);
2604 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2607 /* unsigned or positive */
2609 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2614 /*-----------------------------------------------------------------*/
2615 /* pic16_outBitC - output a bit C */
2616 /* Move to result the value of Carry flag -- VR */
2617 /*-----------------------------------------------------------------*/
2618 void pic16_outBitC(operand *result)
2622 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2624 /* if the result is bit */
2625 if (AOP_TYPE(result) == AOP_CRY) {
2626 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2627 pic16_aopPut(AOP(result),"c",0);
2630 i = AOP_SIZE(result);
2632 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2634 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2638 /*-----------------------------------------------------------------*/
2639 /* pic16_outBitOp - output a bit from Op */
2640 /* Move to result the value of set/clr op -- VR */
2641 /*-----------------------------------------------------------------*/
2642 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2646 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2648 /* if the result is bit */
2649 if (AOP_TYPE(result) == AOP_CRY) {
2650 fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2651 pic16_aopPut(AOP(result),"c",0);
2654 i = AOP_SIZE(result);
2656 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2658 pic16_emitpcode(POC_RRCF, pcop);
2659 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2663 /*-----------------------------------------------------------------*/
2664 /* pic16_toBoolean - emit code for orl a,operator(sizeop) */
2665 /*-----------------------------------------------------------------*/
2666 void pic16_toBoolean(operand *oper)
2668 int size = AOP_SIZE(oper) - 1;
2671 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2673 if ( AOP_TYPE(oper) != AOP_ACC) {
2674 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2677 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2682 #if !defined(GEN_Not)
2683 /*-----------------------------------------------------------------*/
2684 /* genNot - generate code for ! operation */
2685 /*-----------------------------------------------------------------*/
2686 static void pic16_genNot (iCode *ic)
2692 /* assign asmOps to operand & result */
2693 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2694 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2696 DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2697 /* if in bit space then a special case */
2698 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2699 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2700 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2701 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2703 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2704 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2705 pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2710 size = AOP_SIZE(IC_LEFT(ic));
2712 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2713 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2714 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2717 pic16_toBoolean(IC_LEFT(ic));
2719 tlbl = newiTempLabel(NULL);
2720 pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2721 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2722 pic16_outBitC(IC_RESULT(ic));
2725 /* release the aops */
2726 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2727 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2732 #if !defined(GEN_Cpl)
2733 /*-----------------------------------------------------------------*/
2734 /* genCpl - generate code for complement */
2735 /*-----------------------------------------------------------------*/
2736 static void pic16_genCpl (iCode *ic)
2742 /* assign asmOps to operand & result */
2743 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2744 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2746 /* if both are in bit space then
2748 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2749 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2751 pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
2752 pic16_emitcode("cpl","c");
2753 pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
2757 size = AOP_SIZE(IC_RESULT(ic));
2760 char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2762 pic16_emitcode("cpl","a");
2763 pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2765 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2766 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
2768 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2769 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2777 /* release the aops */
2778 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2779 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2783 /*-----------------------------------------------------------------*/
2784 /* genUminusFloat - unary minus for floating points */
2785 /*-----------------------------------------------------------------*/
2786 static void genUminusFloat(operand *op,operand *result)
2788 int size ,offset =0 ;
2791 /* for this we just need to flip the
2792 first it then copy the rest in place */
2793 size = AOP_SIZE(op);
2796 pic16_mov2f(AOP(result), AOP(op), offset);
2800 /* toggle the MSB's highest bit */
2801 pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2804 /*-----------------------------------------------------------------*/
2805 /* genUminus - unary minus code generation */
2806 /*-----------------------------------------------------------------*/
2807 static void genUminus (iCode *ic)
2810 sym_link *optype, *rtype;
2817 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2818 pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2820 /* if both in bit space then special case */
2821 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2822 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2824 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2825 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2826 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
2830 optype = operandType(IC_LEFT(ic));
2831 rtype = operandType(IC_RESULT(ic));
2833 /* if float then do float stuff */
2834 if (IS_FLOAT(optype)) {
2835 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2839 /* otherwise subtract from zero by taking the 2's complement */
2840 size = AOP_SIZE(IC_LEFT(ic));
2841 label = newiTempLabel ( NULL );
2843 if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2844 for (i=size-1; i > 0; i--) {
2845 pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2847 pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2848 for (i=1; i < size; i++) {
2849 if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2850 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2853 for (i=size-1; i >= 0; i--) {
2854 pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2855 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2858 for (i=0; i < size-2; i++) {
2859 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2860 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2862 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2864 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2867 pic16_emitpLabel (label->key);
2870 /* release the aops */
2871 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2872 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2876 /*-----------------------------------------------------------------*/
2877 /* saveRegisters - will look for a call and save the registers */
2878 /*-----------------------------------------------------------------*/
2879 static void saveRegisters(iCode *lic)
2886 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2888 for (ic = lic ; ic ; ic = ic->next)
2889 if (ic->op == CALL || ic->op == PCALL)
2893 fprintf(stderr,"found parameter push with no function call\n");
2897 /* if the registers have been saved already then
2899 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2902 /* find the registers in use at this time
2903 and push them away to safety */
2904 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2908 if (options.useXstack) {
2909 if (bitVectBitValue(rsave,R0_IDX))
2910 pic16_emitcode("mov","b,r0");
2911 pic16_emitcode("mov","r0,%s",spname);
2912 for (i = 0 ; i < pic16_nRegs ; i++) {
2913 if (bitVectBitValue(rsave,i)) {
2915 pic16_emitcode("mov","a,b");
2917 pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2918 pic16_emitcode("movx","@r0,a");
2919 pic16_emitcode("inc","r0");
2922 pic16_emitcode("mov","%s,r0",spname);
2923 if (bitVectBitValue(rsave,R0_IDX))
2924 pic16_emitcode("mov","r0,b");
2926 //for (i = 0 ; i < pic16_nRegs ; i++) {
2927 // if (bitVectBitValue(rsave,i))
2928 // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2931 dtype = operandType(IC_LEFT(ic));
2932 if (currFunc && dtype &&
2933 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2934 IFFUNC_ISISR(currFunc->type) &&
2937 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2940 /*-----------------------------------------------------------------*/
2941 /* unsaveRegisters - pop the pushed registers */
2942 /*-----------------------------------------------------------------*/
2943 static void unsaveRegisters (iCode *ic)
2948 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2949 /* find the registers in use at this time
2950 and push them away to safety */
2951 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2954 if (options.useXstack) {
2955 pic16_emitcode("mov","r0,%s",spname);
2956 for (i = pic16_nRegs ; i >= 0 ; i--) {
2957 if (bitVectBitValue(rsave,i)) {
2958 pic16_emitcode("dec","r0");
2959 pic16_emitcode("movx","a,@r0");
2961 pic16_emitcode("mov","b,a");
2963 pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2967 pic16_emitcode("mov","%s,r0",spname);
2968 if (bitVectBitValue(rsave,R0_IDX))
2969 pic16_emitcode("mov","r0,b");
2971 //for (i = pic16_nRegs ; i >= 0 ; i--) {
2972 // if (bitVectBitValue(rsave,i))
2973 // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2980 /*-----------------------------------------------------------------*/
2982 /*-----------------------------------------------------------------*/
2983 static void pushSide(operand * oper, int size)
2986 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2988 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2989 if (AOP_TYPE(oper) != AOP_REG &&
2990 AOP_TYPE(oper) != AOP_DIR &&
2992 pic16_emitcode("mov","a,%s",l);
2993 pic16_emitcode("push","acc");
2995 pic16_emitcode("push","%s",l);
3000 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
3002 if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3003 pic16_emitpcode(POC_MOVFW, src);
3004 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
3006 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3007 src, pic16_popGet(AOP(op), offset)));
3012 /*-----------------------------------------------------------------*/
3013 /* assignResultValue - assign results to oper, rescall==1 is */
3014 /* called from genCall() or genPcall() */
3015 /*-----------------------------------------------------------------*/
3016 static void assignResultValue(operand * oper, int rescall)
3018 int size = AOP_SIZE(oper);
3022 // DEBUGpic16_emitcode ("; ***","%s %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3023 DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3026 /* assign result from a call/pcall function() */
3028 /* function results are stored in a special order,
3029 * see top of file with Function return policy, or manual */
3032 /* 8-bits, result in WREG */
3033 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3036 /* 16-bits, result in PRODL:WREG */
3037 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3041 /* 24-bits, result in PRODH:PRODL:WREG */
3042 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3046 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3047 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3051 /* >32-bits, result on stack, and FSR0 points to beginning.
3052 * Fix stack when done */
3054 // debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3056 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3057 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3059 popaopidx(AOP(oper), size, GpsuedoStkPtr);
3064 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3065 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3066 if(STACK_MODEL_LARGE) {
3068 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3072 int areg = 0; /* matching argument register */
3074 // debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3075 areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3078 /* its called from genReceive (probably) -- VR */
3079 /* I hope this code will not be called from somewhere else in the future!
3080 * We manually set the pseudo stack pointer in genReceive. - dw
3082 if(!GpsuedoStkPtr && _G.useWreg) {
3083 // DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3085 /* The last byte in the assignment is in W */
3086 if(areg <= GpsuedoStkPtr) {
3088 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3090 // debugf("receive from WREG\n", 0);
3092 GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3095 _G.stack_lat = AOP_SIZE(oper)-1;
3100 popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3101 // debugf("receive from STACK\n", 0);
3108 /*-----------------------------------------------------------------*/
3109 /* genIpush - generate code for pushing this gets a little complex */
3110 /*-----------------------------------------------------------------*/
3111 static void genIpush (iCode *ic)
3113 // int size, offset=0;
3116 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3119 pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3121 /* send to stack as normal */
3122 addSet(&_G.sendSet,ic);
3123 // addSetHead(&_G.sendSet,ic);
3124 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3129 int size, offset = 0 ;
3133 /* if this is not a parm push : ie. it is spill push
3134 and spill push is always done on the local stack */
3135 if (!ic->parmPush) {
3137 /* and the item is spilt then do nothing */
3138 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3141 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3142 size = AOP_SIZE(IC_LEFT(ic));
3143 /* push it on the stack */
3145 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3150 pic16_emitcode("push","%s",l);
3155 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3159 /*-----------------------------------------------------------------*/
3160 /* genIpop - recover the registers: can happen only for spilling */
3161 /*-----------------------------------------------------------------*/
3162 static void genIpop (iCode *ic)
3165 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3170 /* if the temp was not pushed then */
3171 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3174 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3175 size = AOP_SIZE(IC_LEFT(ic));
3178 pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3181 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3186 /*-----------------------------------------------------------------*/
3187 /* unsaverbank - restores the resgister bank from stack */
3188 /*-----------------------------------------------------------------*/
3189 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3191 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3197 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3199 if (options.useXstack) {
3201 r = getFreePtr(ic,&aop,FALSE);
3204 pic16_emitcode("mov","%s,_spx",r->name);
3205 pic16_emitcode("movx","a,@%s",r->name);
3206 pic16_emitcode("mov","psw,a");
3207 pic16_emitcode("dec","%s",r->name);
3210 pic16_emitcode ("pop","psw");
3213 for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3214 if (options.useXstack) {
3215 pic16_emitcode("movx","a,@%s",r->name);
3216 //pic16_emitcode("mov","(%s+%d),a",
3217 // regspic16[i].base,8*bank+regspic16[i].offset);
3218 pic16_emitcode("dec","%s",r->name);
3221 pic16_emitcode("pop",""); //"(%s+%d)",
3222 //regspic16[i].base,8*bank); //+regspic16[i].offset);
3225 if (options.useXstack) {
3227 pic16_emitcode("mov","_spx,%s",r->name);
3228 pic16_freeAsmop(NULL,aop,ic,TRUE);
3234 /*-----------------------------------------------------------------*/
3235 /* saverbank - saves an entire register bank on the stack */
3236 /*-----------------------------------------------------------------*/
3237 static void saverbank (int bank, iCode *ic, bool pushPsw)
3239 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3245 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3246 if (options.useXstack) {
3249 r = getFreePtr(ic,&aop,FALSE);
3250 pic16_emitcode("mov","%s,_spx",r->name);
3254 for (i = 0 ; i < pic16_nRegs ;i++) {
3255 if (options.useXstack) {
3256 pic16_emitcode("inc","%s",r->name);
3257 //pic16_emitcode("mov","a,(%s+%d)",
3258 // regspic16[i].base,8*bank+regspic16[i].offset);
3259 pic16_emitcode("movx","@%s,a",r->name);
3261 pic16_emitcode("push","");// "(%s+%d)",
3262 //regspic16[i].base,8*bank+regspic16[i].offset);
3266 if (options.useXstack) {
3267 pic16_emitcode("mov","a,psw");
3268 pic16_emitcode("movx","@%s,a",r->name);
3269 pic16_emitcode("inc","%s",r->name);
3270 pic16_emitcode("mov","_spx,%s",r->name);
3271 pic16_freeAsmop (NULL,aop,ic,TRUE);
3274 pic16_emitcode("push","psw");
3276 pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3284 static int wparamCmp(void *p1, void *p2)
3286 return (!strcmp((char *)p1, (char *)p2));
3289 int inWparamList(char *s)
3291 return isinSetWith(wparamList, s, wparamCmp);
3295 /*-----------------------------------------------------------------*/
3296 /* genCall - generates a call statement */
3297 /*-----------------------------------------------------------------*/
3298 static void genCall (iCode *ic)
3308 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3309 /* if caller saves & we have not saved then */
3310 // if (!ic->regsSaved)
3311 // saveRegisters(ic);
3313 /* initialise stackParms for IPUSH pushes */
3314 // stackParms = psuedoStkPtr;
3315 // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3316 fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3317 inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3320 gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3323 /* if send set is not empty the assign */
3326 int psuedoStkPtr=-1;
3327 int firstTimeThruLoop = 1;
3330 /* reverse sendSet if function is not reentrant */
3331 if(!IFFUNC_ISREENT(ftype))
3332 _G.sendSet = reverseSet(_G.sendSet);
3334 /* First figure how many parameters are getting passed */
3338 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3342 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3343 size = AOP_SIZE(IC_LEFT(sic));
3347 /* pass the last byte through WREG */
3351 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3352 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3353 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3355 if(!firstTimeThruLoop) {
3356 /* If this is not the first time we've been through the loop
3357 * then we need to save the parameter in a temporary
3358 * register. The last byte of the last parameter is
3362 // --psuedoStkPtr; // sanity check
3366 firstTimeThruLoop=0;
3368 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3373 /* all arguments are passed via stack */
3377 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3378 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3379 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3381 // pushaop(AOP(IC_LEFT(sic)), size);
3382 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3389 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3393 if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3394 pushw(); /* save last parameter to stack if functions has varargs */
3398 } else use_wreg = 0;
3400 _G.stackRegSet = _G.sendSet;
3405 pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3409 /* if we need to assign a result value */
3410 if ((IS_ITEMP(IC_RESULT(ic))
3411 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3412 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3413 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3416 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3419 assignResultValue(IC_RESULT(ic), 1);
3421 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3422 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3424 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3427 if(!stackParms && ic->parmBytes) {
3428 stackParms = ic->parmBytes;
3431 stackParms -= use_wreg;
3434 if(stackParms == 1) {
3435 pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3437 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3438 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l ));
3440 if(STACK_MODEL_LARGE) {
3442 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h ));
3447 gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3450 /* adjust the stack for parameters if required */
3451 // fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3454 /* if register bank was saved then pop them */
3456 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3458 /* if we hade saved some registers then unsave them */
3459 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3460 unsaveRegisters (ic);
3466 /*-----------------------------------------------------------------*/
3467 /* genPcall - generates a call by pointer statement */
3468 /* new version, created from genCall - HJD */
3469 /*-----------------------------------------------------------------*/
3470 static void genPcall (iCode *ic)
3472 sym_link *ftype, *fntype;
3474 symbol *retlbl = newiTempLabel(NULL);
3475 pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3479 ftype = OP_SYM_TYPE(IC_LEFT(ic));
3480 fntype = operandType( IC_LEFT(ic) )->next;
3482 /* if send set is not empty the assign */
3485 int psuedoStkPtr=-1;
3487 /* reverse sendSet if function is not reentrant */
3488 if(!IFFUNC_ISREENT(fntype))
3489 _G.sendSet = reverseSet(_G.sendSet);
3493 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3496 pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3497 size = AOP_SIZE(IC_LEFT(sic));
3500 /* all parameters are passed via stack, since WREG is clobbered
3501 * by the calling sequence */
3503 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3504 pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3505 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3507 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3511 pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3514 _G.stackRegSet = _G.sendSet;
3518 pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3520 // push return address
3521 // push $ on return stack, then replace with retlbl
3523 /* Thanks to Thorsten Klose for pointing out that the following
3524 * snippet should be interrupt safe */
3525 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3526 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3528 pic16_emitpcodeNULLop(POC_PUSH);
3530 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3531 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3532 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3533 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3534 pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3535 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3538 /* restore interrupt control register */
3539 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3540 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3542 /* make the call by writing the pointer into pc */
3543 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3544 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3546 // note: MOVFF to PCL not allowed
3547 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3548 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3551 /* return address is here: (X) */
3552 pic16_emitpLabelFORCE(retlbl->key);
3554 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3557 /* if we need assign a result value */
3558 if ((IS_ITEMP(IC_RESULT(ic))
3559 && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3560 || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3561 || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3564 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3567 assignResultValue(IC_RESULT(ic), 1);
3569 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3570 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3572 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3575 // stackParms -= use_wreg;
3578 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3579 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3580 if(STACK_MODEL_LARGE) {
3582 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3587 /*-----------------------------------------------------------------*/
3588 /* resultRemat - result is rematerializable */
3589 /*-----------------------------------------------------------------*/
3590 static int resultRemat (iCode *ic)
3592 // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3593 if (SKIP_IC(ic) || ic->op == IFX)
3596 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3597 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3598 if (sym->remat && !POINTER_SET(ic))
3605 #if defined(__BORLANDC__) || defined(_MSC_VER)
3606 #define STRCASECMP stricmp
3608 #define STRCASECMP strcasecmp
3612 /*-----------------------------------------------------------------*/
3613 /* inExcludeList - return 1 if the string is in exclude Reg list */
3614 /*-----------------------------------------------------------------*/
3615 static bool inExcludeList(char *s)
3617 DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__);
3620 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3621 if (options.excludeRegs[i] &&
3622 STRCASECMP(options.excludeRegs[i],"none") == 0)
3625 for ( i = 0 ; options.excludeRegs[i]; i++) {
3626 if (options.excludeRegs[i] &&
3627 STRCASECMP(s,options.excludeRegs[i]) == 0)
3634 /*-----------------------------------------------------------------*/
3635 /* genFunction - generated code for function entry */
3636 /*-----------------------------------------------------------------*/
3637 static void genFunction (iCode *ic)
3643 DEBUGpic16_emitcode ("; ***","%s %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3645 pic16_labelOffset += (max_key+4);
3650 ftype = operandType(IC_LEFT(ic));
3651 sym = OP_SYMBOL(IC_LEFT(ic));
3653 if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3654 /* create an absolute section at the interrupt vector:
3655 * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3660 // debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3662 if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3663 sprintf(asymname, "ivec_%s", sym->name);
3665 sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3667 /* when an interrupt is declared as naked, do not emit the special
3668 * wrapper segment at vector address. The user should take care for
3669 * this instead. -- VR */
3671 if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3672 asym = newSymbol(asymname, 0);
3673 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3674 pic16_addpBlock( apb );
3676 pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3677 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3678 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3679 //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3680 pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3682 /* mark the end of this tiny function */
3683 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3685 sprintf(asymname, "%s", sym->rname);
3691 abSym = Safe_calloc(1, sizeof(absSym));
3692 strcpy(abSym->name, asymname);
3694 switch( FUNC_INTNO(sym->type) ) {
3695 case 0: abSym->address = 0x000000; break;
3696 case 1: abSym->address = 0x000008; break;
3697 case 2: abSym->address = 0x000018; break;
3700 // fprintf(stderr, "no interrupt number is given\n");
3701 abSym->address = -1; break;
3704 /* relocate interrupt vectors if needed */
3705 if(abSym->address != -1)
3706 abSym->address += pic16_options.ivt_loc;
3708 addSet(&absSymSet, abSym);
3712 /* create the function header */
3713 pic16_emitcode(";","-----------------------------------------");
3714 pic16_emitcode(";"," function %s",sym->name);
3715 pic16_emitcode(";","-----------------------------------------");
3717 pic16_emitcode("","%s:",sym->rname);
3718 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3723 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3724 if(!strcmp(ab->name, sym->rname)) {
3725 pic16_pBlockConvert2Absolute(pb);
3731 if(IFFUNC_ISNAKED(ftype)) {
3732 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3736 /* if critical function then turn interrupts off */
3737 if (IFFUNC_ISCRITICAL(ftype)) {
3738 //pic16_emitcode("clr","ea");
3741 currFunc = sym; /* update the currFunc symbol */
3742 _G.fregsUsed = sym->regsUsed;
3743 _G.sregsAlloc = newBitVect(128);
3746 /* if this is an interrupt service routine then
3747 * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3748 if (IFFUNC_ISISR(sym->type)) {
3749 _G.usefastretfie = 1; /* use shadow registers by default */
3751 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3752 if(!FUNC_ISSHADOWREGS(sym->type)) {
3753 /* do not save WREG,STATUS,BSR for high priority interrupts
3754 * because they are stored in the hardware shadow registers already */
3755 _G.usefastretfie = 0;
3756 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3757 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3758 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3761 /* these should really be optimized somehow, because not all
3762 * interrupt handlers modify them */
3763 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3764 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3765 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3766 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3768 // pic16_pBlockConvert2ISR(pb);
3771 /* emit code to setup stack frame if user enabled,
3772 * and function is not main() */
3774 // debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3775 if(strcmp(sym->name, "main")) {
3777 || !options.ommitFramePtr
3779 || IFFUNC_ARGS(sym->type)
3780 || FUNC_HASSTACKPARM(sym->etype)
3782 /* setup the stack frame */
3783 if(STACK_MODEL_LARGE)
3784 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3785 pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3787 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3788 if(STACK_MODEL_LARGE)
3789 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3793 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3796 if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3798 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3799 pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l));
3801 pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h));
3804 if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3805 if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3812 /* if callee-save to be used for this function
3813 * then save the registers being used in this function */
3814 // if (IFFUNC_CALLEESAVES(sym->type))
3818 /* if any registers used */
3819 if (sym->regsUsed) {
3820 /* save the registers used */
3821 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3822 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3823 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3824 if (bitVectBitValue(sym->regsUsed,i)) {
3825 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3828 if(!pic16_regWithIdx(i)->wasUsed) {
3829 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3830 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3831 pic16_regWithIdx(i)->wasUsed = 1;
3835 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3839 DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3840 // fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3843 /*-----------------------------------------------------------------*/
3844 /* genEndFunction - generates epilogue for functions */
3845 /*-----------------------------------------------------------------*/
3846 static void genEndFunction (iCode *ic)
3848 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3852 if(IFFUNC_ISNAKED(sym->type)) {
3853 DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3859 /* add code for ISCRITICAL */
3860 if(IFFUNC_ISCRITICAL(sym->type)) {
3861 /* if critical function, turn on interrupts */
3863 /* TODO: add code here -- VR */
3866 // sym->regsUsed = _G.fregsUsed;
3868 /* now we need to restore the registers */
3869 /* if any registers used */
3871 /* first restore registers that might be used for stack access */
3872 if(_G.sregsAllocSet) {
3875 _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3876 for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3877 pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3881 if (sym->regsUsed) {
3884 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3885 /* restore registers used */
3886 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3887 for ( i = sym->regsUsed->size; i >= 0; i--) {
3888 if (bitVectBitValue(sym->regsUsed,i)) {
3889 pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3893 pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3898 if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3900 if (sym->stack == 1) {
3901 pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3902 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3904 // we have to add more than one...
3905 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value!
3906 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3907 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3909 pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3910 pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3911 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3915 if(strcmp(sym->name, "main")) {
3917 || !options.ommitFramePtr
3919 || IFFUNC_ARGS(sym->type)
3920 || FUNC_HASSTACKPARM(sym->etype)
3922 /* restore stack frame */
3923 if(STACK_MODEL_LARGE)
3924 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3925 pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3931 if (IFFUNC_ISISR(sym->type)) {
3932 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3933 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3934 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3935 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3937 if(!FUNC_ISSHADOWREGS(sym->type)) {
3938 /* do not restore interrupt vector for WREG,STATUS,BSR
3939 * for high priority interrupt, see genFunction */
3940 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3941 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3942 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3944 // _G.interruptvector = 0; /* sanity check */
3947 /* if debug then send end of function */
3948 /* if (options.debug && currFunc) */
3950 debugFile->writeEndFunction (currFunc, ic, 1);
3953 if(_G.usefastretfie)
3954 pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3956 pic16_emitpcodeNULLop(POC_RETFIE);
3958 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3960 _G.usefastretfie = 0;
3964 if (IFFUNC_ISCRITICAL(sym->type)) {
3965 pic16_emitcode("setb","ea");
3968 /* if debug then send end of function */
3970 debugFile->writeEndFunction (currFunc, ic, 1);
3973 /* insert code to restore stack frame, if user enabled it
3974 * and function is not main() */
3977 pic16_emitpcodeNULLop(POC_RETURN);
3979 /* Mark the end of a function */
3980 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3984 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3986 unsigned long lit=1;
3991 // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3992 if(AOP_TYPE(op) == AOP_LIT) {
3993 if(!IS_FLOAT(operandType( op ))) {
3994 lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3997 unsigned long lit_int;
4001 /* take care if literal is a float */
4002 info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4008 if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
4009 pic16_emitpcode(POC_CLRF, dest);
4011 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
4012 if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
4015 if(dest->type == PO_WREG && (offset == 0)) {
4016 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4019 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4023 /*-----------------------------------------------------------------*/
4024 /* genRet - generate code for return statement */
4025 /*-----------------------------------------------------------------*/
4026 static void genRet (iCode *ic)
4032 /* if we have no return value then
4033 * just generate the "ret" */
4038 /* we have something to return then
4039 * move the return value into place */
4040 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4041 size = AOP_SIZE(IC_LEFT(ic));
4045 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4048 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4051 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4053 pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4056 /* >32-bits, setup stack and FSR0 */
4058 // DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4059 // DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4061 pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4063 // popaopidx(AOP(oper), size, GpseudoStkPtr);
4068 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4069 pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4071 if(STACK_MODEL_LARGE) {
4072 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4073 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4075 pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4080 /* old code, left here for reference -- VR */
4084 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4086 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4087 pic16_emitpcomment("push %s",l);
4090 DEBUGpic16_emitcode(";", "%d", __LINE__);
4091 l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4092 DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4094 if (strcmp(fReturn[offset],l)) {
4095 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4096 || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4097 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4099 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4103 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4113 if (strcmp(fReturn[pushed],"a"))
4114 pic16_emitcode("pop",fReturn[pushed]);
4116 pic16_emitcode("pop","acc");
4122 pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4125 /* generate a jump to the return label
4126 * if the next is not the return statement */
4127 if (!(ic->next && ic->next->op == LABEL
4128 && IC_LABEL(ic->next) == returnLabel)) {
4130 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4131 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4135 /*-----------------------------------------------------------------*/
4136 /* genLabel - generates a label */
4137 /*-----------------------------------------------------------------*/
4138 static void genLabel (iCode *ic)
4142 /* special case never generate */
4143 if (IC_LABEL(ic) == entryLabel)
4146 pic16_emitpLabel(IC_LABEL(ic)->key);
4147 // pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4150 /*-----------------------------------------------------------------*/
4151 /* genGoto - generates a goto */
4152 /*-----------------------------------------------------------------*/
4154 static void genGoto (iCode *ic)
4157 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4158 // pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4162 /*-----------------------------------------------------------------*/
4163 /* genMultbits :- multiplication of bits */
4164 /*-----------------------------------------------------------------*/
4165 static void genMultbits (operand *left,
4171 if(!pic16_sameRegs(AOP(result),AOP(right)))
4172 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
4174 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4175 pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4176 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
4181 /*-----------------------------------------------------------------*/
4182 /* genMultOneByte : 8 bit multiplication & division */
4183 /*-----------------------------------------------------------------*/
4184 static void genMultOneByte (operand *left,
4190 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4191 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4193 /* (if two literals, the value is computed before) */
4194 /* if one literal, literal on the right */
4195 if (AOP_TYPE(left) == AOP_LIT){
4201 /* size is already checked in genMult == 1 */
4202 // size = AOP_SIZE(result);
4204 if (AOP_TYPE(right) == AOP_LIT){
4205 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4206 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4207 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4208 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4210 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4211 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4212 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4213 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4216 pic16_genMult8X8_8 (left, right,result);
4219 /*-----------------------------------------------------------------*/
4220 /* genMultOneWord : 16 bit multiplication */
4221 /*-----------------------------------------------------------------*/
4222 static void genMultOneWord (operand *left,
4227 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4228 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4230 /* (if two literals, the value is computed before)
4231 * if one literal, literal on the right */
4232 if (AOP_TYPE(left) == AOP_LIT){
4238 /* size is checked already == 2 */
4239 // size = AOP_SIZE(result);
4241 if (AOP_TYPE(right) == AOP_LIT) {
4242 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4243 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4244 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4245 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4247 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4248 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4249 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4250 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4253 pic16_genMult16X16_16(left, right,result);
4256 /*-----------------------------------------------------------------*/
4257 /* genMultOneLong : 32 bit multiplication */
4258 /*-----------------------------------------------------------------*/
4259 static void genMultOneLong (operand *left,
4264 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4265 DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4267 /* (if two literals, the value is computed before)
4268 * if one literal, literal on the right */
4269 if (AOP_TYPE(left) == AOP_LIT){
4275 /* size is checked already == 4 */
4276 // size = AOP_SIZE(result);
4278 if (AOP_TYPE(right) == AOP_LIT) {
4279 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4280 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4281 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4282 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4284 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4285 pic16_aopGet(AOP(right),0,FALSE,FALSE),
4286 pic16_aopGet(AOP(left),0,FALSE,FALSE),
4287 pic16_aopGet(AOP(result),0,FALSE,FALSE));
4290 pic16_genMult32X32_32(left, right,result);
4295 /*-----------------------------------------------------------------*/
4296 /* genMult - generates code for multiplication */
4297 /*-----------------------------------------------------------------*/
4298 static void genMult (iCode *ic)
4300 operand *left = IC_LEFT(ic);
4301 operand *right = IC_RIGHT(ic);
4302 operand *result= IC_RESULT(ic);
4305 /* assign the amsops */
4306 pic16_aopOp (left,ic,FALSE);
4307 pic16_aopOp (right,ic,FALSE);
4308 pic16_aopOp (result,ic,TRUE);
4310 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4312 /* special cases first *
4314 if (AOP_TYPE(left) == AOP_CRY
4315 && AOP_TYPE(right)== AOP_CRY) {
4316 genMultbits(left,right,result);
4320 /* if both are of size == 1 */
4321 if(AOP_SIZE(left) == 1
4322 && AOP_SIZE(right) == 1) {
4323 genMultOneByte(left,right,result);
4327 /* if both are of size == 2 */
4328 if(AOP_SIZE(left) == 2
4329 && AOP_SIZE(right) == 2) {
4330 genMultOneWord(left, right, result);
4334 /* if both are of size == 4 */
4335 if(AOP_SIZE(left) == 4
4336 && AOP_SIZE(right) == 4) {
4337 genMultOneLong(left, right, result);
4341 pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4344 fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4345 /* should have been converted to function call */
4349 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4350 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4351 pic16_freeAsmop(result,NULL,ic,TRUE);
4354 /*-----------------------------------------------------------------*/
4355 /* genDivbits :- division of bits */
4356 /*-----------------------------------------------------------------*/
4357 static void genDivbits (operand *left,
4364 /* the result must be bit */
4365 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4366 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4370 pic16_emitcode("div","ab");
4371 pic16_emitcode("rrc","a");
4372 pic16_aopPut(AOP(result),"c",0);
4375 /*-----------------------------------------------------------------*/
4376 /* genDivOneByte : 8 bit division */
4377 /*-----------------------------------------------------------------*/
4378 static void genDivOneByte (operand *left,
4382 sym_link *opetype = operandType(result);
4387 /* result = divident / divisor
4388 * - divident may be a register or a literal,
4389 * - divisor may be a register or a literal,
4390 * so there are 3 cases (literal / literal is optimized
4391 * by the front-end) to handle.
4392 * In addition we must handle signed and unsigned, which
4393 * result in 6 final different cases -- VR */
4397 size = AOP_SIZE(result) - 1;
4399 /* signed or unsigned */
4400 if (SPEC_USIGN(opetype)) {
4401 pCodeOp *pct1, /* count */
4404 symbol *label1, *label2, *label3;;
4407 /* unsigned is easy */
4409 pct1 = pic16_popGetTempReg(1);
4410 pct2 = pic16_popGetTempReg(1);
4411 pct3 = pic16_popGetTempReg(1);
4413 label1 = newiTempLabel(NULL);
4414 label2 = newiTempLabel(NULL);
4415 label3 = newiTempLabel(NULL);
4417 /* the following algorithm is extracted from divuint.c */
4419 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4420 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4422 pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4424 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4426 pic16_emitpLabel(label1->key);
4429 pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4433 pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4437 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4439 pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4440 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4442 pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4443 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4444 pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4446 pic16_emitpLabel( label3->key );
4447 pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4448 pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4452 pic16_emitpLabel(label2->key);
4453 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4454 pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4455 pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4457 /* result is in wreg */
4458 if(AOP_TYPE(result) != AOP_ACC)
4459 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4461 pic16_popReleaseTempReg( pct3, 1);
4462 pic16_popReleaseTempReg( pct2, 1);
4463 pic16_popReleaseTempReg( pct1, 1);
4468 /* signed is a little bit more difficult */
4470 /* save the signs of the operands */
4471 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4473 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4474 pic16_emitcode("push","acc"); /* save it on the stack */
4476 /* now sign adjust for both left & right */
4477 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4479 lbl = newiTempLabel(NULL);
4480 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4481 pic16_emitcode("cpl","a");
4482 pic16_emitcode("inc","a");
4483 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4484 pic16_emitcode("mov","b,a");
4486 /* sign adjust left side */
4487 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4490 lbl = newiTempLabel(NULL);
4491 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4492 pic16_emitcode("cpl","a");
4493 pic16_emitcode("inc","a");
4494 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4496 /* now the division */
4497 pic16_emitcode("div","ab");
4498 /* we are interested in the lower order
4500 pic16_emitcode("mov","b,a");
4501 lbl = newiTempLabel(NULL);
4502 pic16_emitcode("pop","acc");
4503 /* if there was an over flow we don't
4504 adjust the sign of the result */
4505 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4506 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4508 pic16_emitcode("clr","a");
4509 pic16_emitcode("subb","a,b");
4510 pic16_emitcode("mov","b,a");
4511 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4513 /* now we are done */
4514 pic16_aopPut(AOP(result),"b",0);
4516 pic16_emitcode("mov","c,b.7");
4517 pic16_emitcode("subb","a,acc");
4520 pic16_aopPut(AOP(result),"a",offset++);
4524 /*-----------------------------------------------------------------*/
4525 /* genDiv - generates code for division */
4526 /*-----------------------------------------------------------------*/
4527 static void genDiv (iCode *ic)
4529 operand *left = IC_LEFT(ic);
4530 operand *right = IC_RIGHT(ic);
4531 operand *result= IC_RESULT(ic);
4534 /* Division is a very lengthy algorithm, so it is better
4535 * to call support routines than inlining algorithm.
4536 * Division functions written here just in case someone
4537 * wants to inline and not use the support libraries -- VR */
4541 /* assign the amsops */
4542 pic16_aopOp (left,ic,FALSE);
4543 pic16_aopOp (right,ic,FALSE);
4544 pic16_aopOp (result,ic,TRUE);
4546 /* special cases first */
4548 if (AOP_TYPE(left) == AOP_CRY &&
4549 AOP_TYPE(right)== AOP_CRY) {
4550 genDivbits(left,right,result);
4554 /* if both are of size == 1 */
4555 if (AOP_SIZE(left) == 1 &&
4556 AOP_SIZE(right) == 1 ) {
4557 genDivOneByte(left,right,result);
4561 /* should have been converted to function call */
4564 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4565 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4566 pic16_freeAsmop(result,NULL,ic,TRUE);
4569 /*-----------------------------------------------------------------*/
4570 /* genModbits :- modulus of bits */
4571 /*-----------------------------------------------------------------*/
4572 static void genModbits (operand *left,
4580 werror(W_POSSBUG2, __FILE__, __LINE__);
4581 /* the result must be bit */
4582 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4583 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4587 pic16_emitcode("div","ab");
4588 pic16_emitcode("mov","a,b");
4589 pic16_emitcode("rrc","a");
4590 pic16_aopPut(AOP(result),"c",0);
4593 /*-----------------------------------------------------------------*/
4594 /* genModOneByte : 8 bit modulus */
4595 /*-----------------------------------------------------------------*/
4596 static void genModOneByte (operand *left,
4600 sym_link *opetype = operandType(result);
4605 werror(W_POSSBUG2, __FILE__, __LINE__);
4607 /* signed or unsigned */
4608 if (SPEC_USIGN(opetype)) {
4609 /* unsigned is easy */
4610 pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4611 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4613 pic16_emitcode("div","ab");
4614 pic16_aopPut(AOP(result),"b",0);
4618 /* signed is a little bit more difficult */
4620 /* save the signs of the operands */
4621 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4624 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4625 pic16_emitcode("push","acc"); /* save it on the stack */
4627 /* now sign adjust for both left & right */
4628 l = pic16_aopGet(AOP(right),0,FALSE,FALSE);
4631 lbl = newiTempLabel(NULL);
4632 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4633 pic16_emitcode("cpl","a");
4634 pic16_emitcode("inc","a");
4635 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4636 pic16_emitcode("mov","b,a");
4638 /* sign adjust left side */
4639 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4642 lbl = newiTempLabel(NULL);
4643 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4644 pic16_emitcode("cpl","a");
4645 pic16_emitcode("inc","a");
4646 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4648 /* now the multiplication */
4649 pic16_emitcode("div","ab");
4650 /* we are interested in the lower order
4652 lbl = newiTempLabel(NULL);
4653 pic16_emitcode("pop","acc");
4654 /* if there was an over flow we don't
4655 adjust the sign of the result */
4656 pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4657 pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4659 pic16_emitcode("clr","a");
4660 pic16_emitcode("subb","a,b");
4661 pic16_emitcode("mov","b,a");
4662 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4664 /* now we are done */
4665 pic16_aopPut(AOP(result),"b",0);
4669 /*-----------------------------------------------------------------*/
4670 /* genMod - generates code for division */
4671 /*-----------------------------------------------------------------*/
4672 static void genMod (iCode *ic)
4674 operand *left = IC_LEFT(ic);
4675 operand *right = IC_RIGHT(ic);
4676 operand *result= IC_RESULT(ic);
4680 /* assign the amsops */
4681 pic16_aopOp (left,ic,FALSE);
4682 pic16_aopOp (right,ic,FALSE);
4683 pic16_aopOp (result,ic,TRUE);
4685 /* special cases first */
4687 if (AOP_TYPE(left) == AOP_CRY &&
4688 AOP_TYPE(right)== AOP_CRY) {
4689 genModbits(left,right,result);
4693 /* if both are of size == 1 */
4694 if (AOP_SIZE(left) == 1 &&
4695 AOP_SIZE(right) == 1 ) {
4696 genModOneByte(left,right,result);
4700 /* should have been converted to function call */
4704 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4705 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4706 pic16_freeAsmop(result,NULL,ic,TRUE);
4709 /*-----------------------------------------------------------------*/
4710 /* genIfxJump :- will create a jump depending on the ifx */
4711 /*-----------------------------------------------------------------*/
4713 note: May need to add parameter to indicate when a variable is in bit space.
4715 static void genIfxJump (iCode *ic, char *jval)
4719 /* if true label then we jump if condition
4721 if ( IC_TRUE(ic) ) {
4723 if(strcmp(jval,"a") == 0)
4725 else if (strcmp(jval,"c") == 0)
4728 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4729 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4732 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4733 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4737 /* false label is present */
4738 if(strcmp(jval,"a") == 0)
4740 else if (strcmp(jval,"c") == 0)
4743 DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4744 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4747 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4748 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4753 /* mark the icode as generated */
4757 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4761 /* if true label then we jump if condition
4763 if ( IC_TRUE(ic) ) {
4764 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4765 pic16_emitpcode(POC_BTFSC, jop);
4767 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4768 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4771 /* false label is present */
4772 DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4773 pic16_emitpcode(POC_BTFSS, jop);
4775 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4776 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4780 /* mark the icode as generated */
4787 /*-----------------------------------------------------------------*/
4789 /*-----------------------------------------------------------------*/
4790 static void genSkip(iCode *ifx,int status_bit)
4792 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4796 if ( IC_TRUE(ifx) ) {
4797 switch(status_bit) {
4812 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4813 // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4817 switch(status_bit) {
4831 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4832 // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4839 /*-----------------------------------------------------------------*/
4841 /*-----------------------------------------------------------------*/
4842 static void genSkipc(resolvedIfx *rifx)
4844 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4854 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4855 rifx->generated = 1;
4858 #if !(USE_SIMPLE_GENCMP)
4859 /*-----------------------------------------------------------------*/
4861 /*-----------------------------------------------------------------*/
4862 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4864 DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4869 if( (rifx->condition ^ invert_condition) & 1)
4874 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4875 rifx->generated = 1;
4880 /*-----------------------------------------------------------------*/
4882 /*-----------------------------------------------------------------*/
4883 static void genSkipz(iCode *ifx, int condition)
4894 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4896 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4899 pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4901 pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4906 #if !(USE_SIMPLE_GENCMP)
4907 /*-----------------------------------------------------------------*/
4909 /*-----------------------------------------------------------------*/
4910 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4916 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4918 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4921 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4922 rifx->generated = 1;
4927 /*-----------------------------------------------------------------*/
4928 /* genChkZeroes :- greater or less than comparison */
4929 /* For each byte in a literal that is zero, inclusive or the */
4930 /* the corresponding byte in the operand with W */
4931 /* returns true if any of the bytes are zero */
4932 /*-----------------------------------------------------------------*/
4933 static int genChkZeroes(operand *op, int lit, int size)
4940 i = (lit >> (size*8)) & 0xff;
4944 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4946 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4956 /*-----------------------------------------------------------------*/
4957 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
4958 /* aop (if it's NOT a literal) or from lit (if */
4959 /* aop is a literal) */
4960 /*-----------------------------------------------------------------*/
4961 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4962 if (aop->type == AOP_LIT) {
4963 pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4965 pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4969 /*-----------------------------------------------------------------*/
4970 /* genCmp :- greater or less than comparison */
4971 /*-----------------------------------------------------------------*/
4973 #if USE_SIMPLE_GENCMP /* { */
4975 /* genCmp performs a left < right comparison, stores
4976 * the outcome in result (if != NULL) and generates
4977 * control flow code for the ifx (if != NULL).
4979 * This version leaves in sequences like
4980 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4981 * which should be optmized by the peephole
4982 * optimizer - RN 2005-01-01 */
4983 static void genCmp (operand *left,operand *right,
4984 operand *result, iCode *ifx, int sign)
4997 assert (AOP_SIZE(left) == AOP_SIZE(right));
4998 assert (left && right);
5000 size = AOP_SIZE(right) - 1;
5001 mask = (0x100UL << (size*8)) - 1;
5002 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5007 resolveIfx (&rIfx, ifx);
5009 /* handle for special cases */
5010 if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5013 /**********************************************************************
5014 * handle bits - bit compares are promoted to int compares seemingly! *
5015 **********************************************************************/
5017 // THIS IS COMPLETELY UNTESTED!
5018 if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5019 pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5020 pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5021 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5024 // 1 < {0,1} is false --> clear C by skipping the next instruction
5025 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5026 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5027 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5028 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5029 emitCLRC; // only skipped for left=0 && right=1
5031 goto correct_result_in_carry;
5035 /*************************************************
5036 * make sure that left is register (or the like) *
5037 *************************************************/
5038 if (!isAOP_REGlike(left)) {
5039 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5040 assert (isAOP_LIT(left));
5041 assert (isAOP_REGlike(right));
5042 // swap left and right
5043 // left < right <==> right > left <==> (right >= left + 1)
5044 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5046 if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5047 // MAXVALUE < right? always false
5048 if (performedLt) emitCLRC; else emitSETC;
5049 goto correct_result_in_carry;
5052 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5053 // that's why we handled it above.
5060 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5061 } else if (isAOP_LIT(right)) {
5062 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5065 assert (isAOP_REGlike(left)); // left must be register or the like
5066 assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5068 /*************************************************
5069 * special cases go here *
5070 *************************************************/
5072 if (isAOP_LIT(right)) {
5074 // unsigned comparison to a literal
5075 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5077 // unsigned left < 0? always false
5078 if (performedLt) emitCLRC; else emitSETC;
5079 goto correct_result_in_carry;
5082 // signed comparison to a literal
5083 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5084 if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5085 // signed left < 0x80000000? always false
5086 if (performedLt) emitCLRC; else emitSETC;
5087 goto correct_result_in_carry;
5088 } else if (lit == 0) {
5089 // compare left < 0; set CARRY if SIGNBIT(left) is set
5090 if (performedLt) emitSETC; else emitCLRC;
5091 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5092 if (performedLt) emitCLRC; else emitSETC;
5093 goto correct_result_in_carry;
5096 } // right is literal
5098 /*************************************************
5099 * perform a general case comparison *
5100 * make sure we get CARRY==1 <==> left >= right *
5101 *************************************************/
5102 // compare most significant bytes
5103 //DEBUGpc ("comparing bytes at offset %d", size);
5105 // unsigned comparison
5106 mov2w_regOrLit (AOP(right), lit, size);
5107 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5109 // signed comparison
5110 // (add 2^n to both operands then perform an unsigned comparison)
5111 if (isAOP_LIT(right)) {
5112 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5113 unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5115 if (litbyte == 0x80) {
5116 // left >= 0x80 -- always true, but more bytes to come
5117 pic16_mov2w (AOP(left), size);
5118 pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5121 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5122 pic16_mov2w (AOP(left), size);
5123 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5124 pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5127 pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5128 //pCodeOp *pctemp = pic16_popGetTempReg(1);
5129 pic16_mov2w (AOP(left), size);
5130 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5131 pic16_emitpcode (POC_MOVWF, pctemp);
5132 pic16_mov2w (AOP(right), size);
5133 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5134 pic16_emitpcode (POC_SUBFW, pctemp);
5135 //pic16_popReleaseTempReg(pctemp, 1);
5139 // compare remaining bytes (treat as unsigned case from above)
5140 templbl = newiTempLabel ( NULL );
5143 //DEBUGpc ("comparing bytes at offset %d", offs);
5144 pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5145 mov2w_regOrLit (AOP(right), lit, offs);
5146 pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5148 pic16_emitpLabel (templbl->key);
5149 goto result_in_carry;
5153 /****************************************************
5154 * now CARRY contains the result of the comparison: *
5155 * SUBWF sets CARRY iff *
5156 * F-W >= 0 <==> F >= W <==> !(F < W) *
5157 * (F=left, W=right) *
5158 ****************************************************/
5161 if (result && AOP_TYPE(result) != AOP_CRY) {
5162 // value will be stored
5165 // value wil only be used in the following genSkipc()
5166 rIfx.condition ^= 1;
5170 correct_result_in_carry:
5172 // assign result to variable (if neccessary)
5173 if (result && AOP_TYPE(result) != AOP_CRY) {
5174 //DEBUGpc ("assign result");
5175 size = AOP_SIZE(result);
5177 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5179 pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5182 // perform conditional jump
5184 //DEBUGpc ("generate control flow");
5193 static void genCmp (operand *left,operand *right,
5194 operand *result, iCode *ifx, int sign)
5196 int size; //, offset = 0 ;
5197 unsigned long lit = 0L,i = 0;
5198 resolvedIfx rFalseIfx;
5199 // resolvedIfx rTrueIfx;
5201 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5204 DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5205 DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5211 resolveIfx(&rFalseIfx,ifx);
5212 truelbl = newiTempLabel(NULL);
5213 size = max(AOP_SIZE(left),AOP_SIZE(right));
5215 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5219 /* if literal is on the right then swap with left */
5220 if ((AOP_TYPE(right) == AOP_LIT)) {
5221 operand *tmp = right ;
5222 unsigned long mask = (0x100 << (8*(size-1))) - 1;
5223 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5226 lit = (lit - 1) & mask;
5229 rFalseIfx.condition ^= 1;
5232 } else if ((AOP_TYPE(left) == AOP_LIT)) {
5233 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5237 //if(IC_TRUE(ifx) == NULL)
5238 /* if left & right are bit variables */
5239 if (AOP_TYPE(left) == AOP_CRY &&
5240 AOP_TYPE(right) == AOP_CRY ) {
5241 assert (0 && "bit variables used in genCmp");
5242 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5243 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5245 /* subtract right from left if at the
5246 end the carry flag is set then we know that
5247 left is greater than right */
5249 symbol *lbl = newiTempLabel(NULL);
5252 fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5253 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5257 if(AOP_TYPE(right) == AOP_LIT) {
5259 //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5261 DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5268 genSkipCond(&rFalseIfx,left,size-1,7);
5270 /* no need to compare to 0...*/
5271 /* NOTE: this is a de-generate compare that most certainly
5272 * creates some dead code. */
5273 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5275 if(ifx) ifx->generated = 1;
5282 //i = (lit >> (size*8)) & 0xff;
5283 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5285 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5287 i = ((0-lit) & 0xff);
5290 /* lit is 0x7f, all signed chars are less than
5291 * this except for 0x7f itself */
5292 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5293 genSkipz2(&rFalseIfx,0);
5295 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5296 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5297 genSkipc(&rFalseIfx);
5302 genSkipz2(&rFalseIfx,1);
5304 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5305 genSkipc(&rFalseIfx);
5309 if(ifx) ifx->generated = 1;
5313 /* chars are out of the way. now do ints and longs */
5316 DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5323 genSkipCond(&rFalseIfx,left,size,7);
5324 if(ifx) ifx->generated = 1;
5329 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5331 //rFalseIfx.condition ^= 1;
5332 //genSkipCond(&rFalseIfx,left,size,7);
5333 //rFalseIfx.condition ^= 1;
5335 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5336 if(rFalseIfx.condition)
5337 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5339 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5341 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5342 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5343 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5346 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5348 if(rFalseIfx.condition) {
5350 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5356 genSkipc(&rFalseIfx);
5357 pic16_emitpLabel(truelbl->key);
5358 if(ifx) ifx->generated = 1;
5365 if( (lit & 0xff) == 0) {
5366 /* lower byte is zero */
5367 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5368 i = ((lit >> 8) & 0xff) ^0x80;
5369 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5370 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5371 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5372 genSkipc(&rFalseIfx);
5375 if(ifx) ifx->generated = 1;
5380 /* Special cases for signed longs */
5381 if( (lit & 0xffffff) == 0) {
5382 /* lower byte is zero */
5383 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5384 i = ((lit >> 8*3) & 0xff) ^0x80;
5385 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5386 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5387 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5388 genSkipc(&rFalseIfx);
5391 if(ifx) ifx->generated = 1;
5399 if(lit & (0x80 << (size*8))) {
5400 /* lit is negative */
5401 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5403 //genSkipCond(&rFalseIfx,left,size,7);
5405 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5407 if(rFalseIfx.condition)
5408 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5410 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5414 /* lit is positive */
5415 DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5416 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5417 if(rFalseIfx.condition)
5418 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5420 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5425 This works, but is only good for ints.
5426 It also requires a "known zero" register.
5427 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5428 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5429 pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero));
5430 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5431 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5432 genSkipc(&rFalseIfx);
5434 pic16_emitpLabel(truelbl->key);
5435 if(ifx) ifx->generated = 1;
5439 /* There are no more special cases, so perform a general compare */
5441 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5442 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5446 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5448 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5450 //rFalseIfx.condition ^= 1;
5451 genSkipc(&rFalseIfx);
5453 pic16_emitpLabel(truelbl->key);
5455 if(ifx) ifx->generated = 1;
5462 /* sign is out of the way. So now do an unsigned compare */
5463 DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5466 /* General case - compare to an unsigned literal on the right.*/
5468 i = (lit >> (size*8)) & 0xff;
5469 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5470 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5472 i = (lit >> (size*8)) & 0xff;
5475 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5477 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5479 /* this byte of the lit is zero,
5480 *if it's not the last then OR in the variable */
5482 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5487 pic16_emitpLabel(lbl->key);
5488 // pic16_emitpLabel(truelbl->key);
5489 //if(emitFinalCheck)
5490 genSkipc(&rFalseIfx);
5492 pic16_emitpLabel(truelbl->key);
5494 if(ifx) ifx->generated = 1;
5501 if(AOP_TYPE(left) == AOP_LIT) {
5502 //symbol *lbl = newiTempLabel(NULL);
5504 //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5507 DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5510 if((lit == 0) && (sign == 0)){
5513 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5515 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5517 genSkipz2(&rFalseIfx,0);
5518 if(ifx) ifx->generated = 1;
5525 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5526 /* degenerate compare can never be true */
5527 if(rFalseIfx.condition == 0)
5528 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5530 if(ifx) ifx->generated = 1;
5535 /* signed comparisons to a literal byte */
5537 int lp1 = (lit+1) & 0xff;
5539 DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5542 rFalseIfx.condition ^= 1;
5543 genSkipCond(&rFalseIfx,right,0,7);
5546 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5547 pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5548 genSkipz2(&rFalseIfx,1);
5551 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5552 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5553 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5554 rFalseIfx.condition ^= 1;
5555 genSkipc(&rFalseIfx);
5559 /* unsigned comparisons to a literal byte */
5561 switch(lit & 0xff ) {
5563 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5564 genSkipz2(&rFalseIfx,0);
5567 rFalseIfx.condition ^= 1;
5568 genSkipCond(&rFalseIfx,right,0,7);
5572 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5573 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5574 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5575 rFalseIfx.condition ^= 1;
5576 if (AOP_TYPE(result) == AOP_CRY)
5577 genSkipc(&rFalseIfx);
5579 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5580 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5586 if(ifx) ifx->generated = 1;
5587 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5593 /* Size is greater than 1 */
5601 /* this means lit = 0xffffffff, or -1 */
5604 DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5605 rFalseIfx.condition ^= 1;
5606 genSkipCond(&rFalseIfx,right,size,7);
5607 if(ifx) ifx->generated = 1;
5609 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5618 if(rFalseIfx.condition) {
5619 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5620 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5623 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5625 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5629 if(rFalseIfx.condition) {
5630 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5631 pic16_emitpLabel(truelbl->key);
5633 rFalseIfx.condition ^= 1;
5634 genSkipCond(&rFalseIfx,right,s,7);
5637 if(ifx) ifx->generated = 1;
5639 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5645 if((size == 1) && (0 == (lp1&0xff))) {
5646 /* lower byte of signed word is zero */
5647 DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit);
5648 i = ((lp1 >> 8) & 0xff) ^0x80;
5649 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5650 pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5651 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5653 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5655 if(ifx) ifx->generated = 1;
5658 rFalseIfx.condition ^= 1;
5659 genSkipc(&rFalseIfx);
5660 if(ifx) ifx->generated = 1;
5666 if(lit & (0x80 << (size*8))) {
5667 /* Lit is less than zero */
5668 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit);
5669 //rFalseIfx.condition ^= 1;
5670 //genSkipCond(&rFalseIfx,left,size,7);
5671 //rFalseIfx.condition ^= 1;
5672 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5673 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5675 if(rFalseIfx.condition)
5676 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5678 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5682 /* Lit is greater than or equal to zero */
5683 DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit);
5684 //rFalseIfx.condition ^= 1;
5685 //genSkipCond(&rFalseIfx,right,size,7);
5686 //rFalseIfx.condition ^= 1;
5688 //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5689 //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5691 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5692 if(rFalseIfx.condition)
5693 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5695 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5699 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5700 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5704 pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5706 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5708 rFalseIfx.condition ^= 1;
5709 //rFalseIfx.condition = 1;
5710 genSkipc(&rFalseIfx);
5712 pic16_emitpLabel(truelbl->key);
5714 if(ifx) ifx->generated = 1;
5717 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5724 /* compare word or long to an unsigned literal on the right.*/
5729 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5732 break; /* handled above */
5735 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5737 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5738 genSkipz2(&rFalseIfx,0);
5742 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5744 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5747 if(rFalseIfx.condition)
5748 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key));
5750 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key));
5753 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5754 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5756 rFalseIfx.condition ^= 1;
5757 genSkipc(&rFalseIfx);
5760 pic16_emitpLabel(truelbl->key);
5762 if(ifx) ifx->generated = 1;
5764 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5772 DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5773 i = (lit >> (size*8)) & 0xff;
5775 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5776 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5779 i = (lit >> (size*8)) & 0xff;
5782 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5784 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5786 /* this byte of the lit is zero,
5787 * if it's not the last then OR in the variable */
5789 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5794 pic16_emitpLabel(lbl->key);
5796 rFalseIfx.condition ^= 1;
5798 genSkipc(&rFalseIfx);
5802 pic16_emitpLabel(truelbl->key);
5803 if(ifx) ifx->generated = 1;
5805 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5811 /* Compare two variables */
5813 DEBUGpic16_emitcode(";sign","%d",sign);
5817 /* Sigh. thus sucks... */
5821 pctemp = pic16_popGetTempReg(1);
5822 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5823 pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5824 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5825 pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5826 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5827 pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5828 pic16_popReleaseTempReg(pctemp, 1);
5830 /* Signed char comparison */
5831 /* Special thanks to Nikolai Golovchenko for this snippet */
5832 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5833 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5834 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */
5835 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5836 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5837 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5839 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5840 genSkipc(&rFalseIfx);
5842 if(ifx) ifx->generated = 1;
5844 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5852 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5853 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5857 /* The rest of the bytes of a multi-byte compare */
5861 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key));
5864 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5865 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5870 pic16_emitpLabel(lbl->key);
5872 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5873 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
5874 (AOP_TYPE(result) == AOP_REG)) {
5875 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5876 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5878 genSkipc(&rFalseIfx);
5880 //genSkipc(&rFalseIfx);
5881 if(ifx) ifx->generated = 1;
5884 if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5892 if ((AOP_TYPE(result) != AOP_CRY)
5893 && AOP_SIZE(result)) {
5894 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5896 if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5898 pic16_outBitC(result);
5900 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5901 /* if the result is used in the next
5902 ifx conditional branch then generate
5903 code a little differently */
5905 genIfxJump (ifx,"c");
5907 pic16_outBitC(result);
5908 /* leave the result in acc */
5913 #elif 0 /* VR version of genCmp() */ /* } else { */
5915 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5916 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5917 operand *result, int offset, int invert_op)
5921 /* check condition, > or < ?? */
5922 if(rIfx->condition != 0)invert_op ^= 1;
5924 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5926 if(!ifx)invert_op ^= 1;
5928 DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5929 __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5932 if(!invert_op)return POC_CPFSGT;
5933 else return POC_CPFSLT;
5936 static int compareAopfirstpass=1;
5938 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5939 operand *oper, int offset, operand *result,
5940 int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5946 /* invert if there is a result to be loaded, in order to fit,
5947 * SETC/CLRC sequence */
5948 if(AOP_SIZE(result))invert_op ^= 1;
5950 // if(sign && !offset)invert_op ^= 1;
5952 // if(sign)invert_op ^= 1;
5954 op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5956 if(AOP_SIZE(result) && compareAopfirstpass) {
5959 pic16_emitpcode(POC_SETF, pcop2);
5964 pic16_emitpcode(POC_CLRF, pcop2);
5970 compareAopfirstpass = 0;
5972 /* there is a bug when comparing operands with size > 1,
5973 * because higher bytes can be equal and test should be performed
5974 * to the next lower byte, current algorithm, considers operands
5975 * inequal in these cases! -- VR 20041107 */
5979 pic16_emitpcode(op, pcop);
5981 pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5984 if((!sign || !offset) && AOP_SIZE(result)) {
5987 pic16_emitpcode(POC_CLRF, pcop2);
5992 pic16_emitpcode(POC_SETF, pcop2);
5997 /* don't emit final branch (offset == 0) */
6001 pic16_emitpcode(POC_RRCF, pcop2);
6003 pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6006 if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6007 DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6008 __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6010 truelbl = newiTempLabel( NULL );
6011 pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6012 if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6013 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6015 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6016 pic16_emitpLabel(truelbl->key);
6018 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6023 static void genCmp (operand *left, operand *right,
6024 operand *result, iCode *ifx, int sign)
6028 resolvedIfx rFalseIfx;
6029 symbol *falselbl, *tlbl;
6033 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6035 resolveIfx(&rFalseIfx, ifx);
6036 size = max(AOP_SIZE(left), AOP_SIZE(right));
6038 /* if left & right are bit variables */
6039 if(AOP_TYPE(left) == AOP_CRY
6040 && AOP_TYPE(right) == AOP_CRY ) {
6042 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6043 pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6045 werror(W_POSSBUG2, __FILE__, __LINE__);
6049 /* if literal is on the right then swap with left */
6050 if((AOP_TYPE(right) == AOP_LIT)) {
6051 operand *tmp = right ;
6052 // unsigned long mask = (0x100 << (8*(size-1))) - 1;
6054 lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6056 // lit = (lit - 1) & mask;
6059 rFalseIfx.condition ^= 1; /* reverse compare */
6061 if ((AOP_TYPE(left) == AOP_LIT)) {
6062 /* float compares are handled by support functions */
6063 lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6066 /* actual comparing algorithm */
6067 // size = AOP_SIZE( right );
6069 falselbl = newiTempLabel( NULL );
6070 if(AOP_TYPE(left) == AOP_LIT) {
6071 /* compare to literal */
6072 DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6075 pCodeOp *pct, *pct2;
6078 /* signed compare */
6079 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6081 pct = pic16_popCopyReg(&pic16_pc_prodl);
6082 pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6083 tlbl = newiTempLabel( NULL );
6085 /* first compare signs:
6086 * a. if both are positive, compare just like unsigned
6087 * b. if both are negative, invert cmpop, compare just like unsigned
6088 * c. if different signs, determine the result directly */
6094 tlbl1 = newiTempLabel( NULL );
6095 // pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */
6099 /* literal is zero or positive:
6100 * a. if carry is zero, too, continue compare,
6101 * b. if carry is set, then continue depending on cmpop ^ condition:
6102 * 1. '<' return false (literal < variable),
6103 * 2. '>' return true (literal > variable) */
6104 // pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6105 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6108 if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6109 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6113 /* literal is negative:
6114 * a. if carry is set, too, continue compare,
6115 * b. if carry is zero, then continue depending on cmpop ^ condition:
6116 * 1. '<' return true (literal < variable),
6117 * 2. '>' return false (literal > variable) */
6118 // pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6119 pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6121 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6122 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6127 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6129 if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6130 else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6135 pic16_emitpLabel( tlbl1->key );
6138 compareAopfirstpass=1;
6139 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6140 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6141 // pic16_emitpcode(POC_MOVWF, pct);
6143 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6144 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6145 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6146 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6150 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6151 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6152 // pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6153 // pic16_emitpcode(POC_MOVWF, pct);
6155 // pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6156 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6157 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6158 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6159 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6162 if(ifx)ifx->generated = 1;
6164 if(AOP_SIZE(result)) {
6165 pic16_emitpLabel(tlbl->key);
6166 pic16_emitpLabel(falselbl->key);
6167 pic16_outBitOp( result, pct2 );
6169 pic16_emitpLabel(tlbl->key);
6173 /* unsigned compare */
6174 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6176 compareAopfirstpass=1;
6179 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6180 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6183 if(ifx)ifx->generated = 1;
6185 if(AOP_SIZE(result)) {
6186 pic16_emitpLabel(falselbl->key);
6187 pic16_outBitC( result );
6192 /* compare registers */
6193 DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6197 pCodeOp *pct, *pct2;
6199 /* signed compare */
6200 DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6202 pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */
6203 pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */
6204 tlbl = newiTempLabel( NULL );
6206 compareAopfirstpass=1;
6209 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6210 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6211 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6212 pic16_emitpcode(POC_MOVWF, pct);
6214 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6215 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6216 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6218 /* WREG already holds left + 0x80 */
6219 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6222 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6223 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6224 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6225 pic16_emitpcode(POC_MOVWF, pct);
6227 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6228 // pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6229 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6231 /* WREG already holds left + 0x80 */
6232 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6233 // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6236 if(ifx)ifx->generated = 1;
6238 if(AOP_SIZE(result)) {
6239 pic16_emitpLabel(tlbl->key);
6240 pic16_emitpLabel(falselbl->key);
6241 pic16_outBitOp( result, pct2 );
6243 pic16_emitpLabel(tlbl->key);
6247 /* unsigned compare */
6248 DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6250 compareAopfirstpass=1;
6253 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6254 compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6258 if(ifx)ifx->generated = 1;
6259 if(AOP_SIZE(result)) {
6261 pic16_emitpLabel(falselbl->key);
6262 pic16_outBitC( result );
6273 /*-----------------------------------------------------------------*/
6274 /* genCmpGt :- greater than comparison */
6275 /*-----------------------------------------------------------------*/
6276 static void genCmpGt (iCode *ic, iCode *ifx)
6278 operand *left, *right, *result;
6279 sym_link *letype , *retype;
6285 right= IC_RIGHT(ic);
6286 result = IC_RESULT(ic);
6288 letype = getSpec(operandType(left));
6289 retype =getSpec(operandType(right));
6290 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6291 /* assign the amsops */
6292 pic16_aopOp (left,ic,FALSE);
6293 pic16_aopOp (right,ic,FALSE);
6294 pic16_aopOp (result,ic,TRUE);
6296 genCmp(right, left, result, ifx, sign);
6298 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6299 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6300 pic16_freeAsmop(result,NULL,ic,TRUE);
6303 /*-----------------------------------------------------------------*/
6304 /* genCmpLt - less than comparisons */
6305 /*-----------------------------------------------------------------*/
6306 static void genCmpLt (iCode *ic, iCode *ifx)
6308 operand *left, *right, *result;
6309 sym_link *letype , *retype;
6315 right= IC_RIGHT(ic);
6316 result = IC_RESULT(ic);
6318 letype = getSpec(operandType(left));
6319 retype =getSpec(operandType(right));
6320 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6322 /* assign the amsops */
6323 pic16_aopOp (left,ic,FALSE);
6324 pic16_aopOp (right,ic,FALSE);
6325 pic16_aopOp (result,ic,TRUE);
6327 genCmp(left, right, result, ifx, sign);
6329 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6330 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6331 pic16_freeAsmop(result,NULL,ic,TRUE);
6336 // FIXME reenable literal optimisation when the pic16 port is stable
6338 /*-----------------------------------------------------------------*/
6339 /* genc16bit2lit - compare a 16 bit value to a literal */
6340 /*-----------------------------------------------------------------*/
6341 static void genc16bit2lit(operand *op, int lit, int offset)
6345 DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit);
6346 if( (lit&0xff) == 0)
6351 switch( BYTEofLONG(lit,i)) {
6353 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6356 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6359 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6362 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6363 pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6368 switch( BYTEofLONG(lit,i)) {
6370 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6374 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6378 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6381 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6383 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6392 /*-----------------------------------------------------------------*/
6393 /* gencjneshort - compare and jump if not equal */
6394 /*-----------------------------------------------------------------*/
6395 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6397 int size = max(AOP_SIZE(left),AOP_SIZE(right));
6399 int res_offset = 0; /* the result may be a different size then left or right */
6400 int res_size = AOP_SIZE(result);
6402 symbol *lbl, *lbl_done;
6404 unsigned long lit = 0L;
6405 int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6407 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6408 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6410 DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
6411 resolveIfx(&rIfx,ifx);
6412 lbl = newiTempLabel(NULL);
6413 lbl_done = newiTempLabel(NULL);
6416 /* if the left side is a literal or
6417 if the right is in a pointer register and left
6419 if ((AOP_TYPE(left) == AOP_LIT) ||
6420 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6425 if(AOP_TYPE(right) == AOP_LIT)
6426 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6428 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6429 preserve_result = 1;
6431 if(result && !preserve_result)
6434 for(i = 0; i < AOP_SIZE(result); i++)
6435 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6439 /* if the right side is a literal then anything goes */
6440 if (AOP_TYPE(right) == AOP_LIT &&
6441 AOP_TYPE(left) != AOP_DIR ) {
6444 genc16bit2lit(left, lit, 0);
6446 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6449 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6452 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6453 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6455 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6459 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6461 if(res_offset < res_size-1)
6469 /* if the right side is in a register or in direct space or
6470 if the left is a pointer register & right is not */
6471 else if (AOP_TYPE(right) == AOP_REG ||
6472 AOP_TYPE(right) == AOP_DIR ||
6473 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6474 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6475 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6476 int lbl_key = lbl->key;
6479 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6480 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6482 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6483 fprintf(stderr, "%s %d error - expecting result to be non_null\n",
6484 __FUNCTION__,__LINE__);
6488 /* switch(size) { */
6490 /* genc16bit2lit(left, lit, 0); */
6492 /* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6497 if((AOP_TYPE(left) == AOP_DIR) &&
6498 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6500 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6501 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6503 } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6505 switch (lit & 0xff) {
6507 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6510 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6511 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6512 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6516 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6517 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6518 //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6519 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6523 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6524 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6529 pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6532 if(AOP_TYPE(result) == AOP_CRY) {
6533 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6538 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6540 /* fix me. probably need to check result size too */
6541 //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6546 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6547 //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6554 if(res_offset < res_size-1)
6559 } else if(AOP_TYPE(right) == AOP_REG &&
6560 AOP_TYPE(left) != AOP_DIR){
6563 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6564 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6565 pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__);
6570 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6572 if(res_offset < res_size-1)
6577 /* right is a pointer reg need both a & b */
6579 char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6581 pic16_emitcode("mov","b,%s",l);
6582 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6583 pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6588 if(result && preserve_result)
6591 for(i = 0; i < AOP_SIZE(result); i++)
6592 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6595 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6597 if(result && preserve_result)
6598 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6601 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6603 pic16_emitpLabel(lbl->key);
6605 if(result && preserve_result)
6608 for(i = 0; i < AOP_SIZE(result); i++)
6609 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6611 pic16_emitpLabel(lbl_done->key);
6614 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6622 /*-----------------------------------------------------------------*/
6623 /* gencjne - compare and jump if not equal */
6624 /*-----------------------------------------------------------------*/
6625 static void gencjne(operand *left, operand *right, iCode *ifx)
6627 symbol *tlbl = newiTempLabel(NULL);
6629 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6630 gencjneshort(left, right, lbl);
6632 pic16_emitcode("mov","a,%s",one);
6633 pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6634 pic16_emitcode("","%05d_DS_:",lbl->key+100);
6635 pic16_emitcode("clr","a");
6636 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6638 pic16_emitpLabel(lbl->key);
6639 pic16_emitpLabel(tlbl->key);
6645 /*-----------------------------------------------------------------*/
6646 /* is_LitOp - check if operand has to be treated as literal */
6647 /*-----------------------------------------------------------------*/
6648 static bool is_LitOp(operand *op)
6650 return ((AOP_TYPE(op) == AOP_LIT)
6651 || ( (AOP_TYPE(op) == AOP_PCODE)
6652 && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6653 || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6656 /*-----------------------------------------------------------------*/
6657 /* is_LitAOp - check if operand has to be treated as literal */
6658 /*-----------------------------------------------------------------*/
6659 static bool is_LitAOp(asmop *aop)
6661 return ((aop->type == AOP_LIT)
6662 || ( (aop->type == AOP_PCODE)
6663 && ( (aop->aopu.pcop->type == PO_LITERAL)
6664 || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6669 /*-----------------------------------------------------------------*/
6670 /* genCmpEq - generates code for equal to */
6671 /*-----------------------------------------------------------------*/
6672 static void genCmpEq (iCode *ic, iCode *ifx)
6674 operand *left, *right, *result;
6675 symbol *falselbl = newiTempLabel(NULL);
6676 symbol *donelbl = newiTempLabel(NULL);
6678 int preserve_result = 0;
6679 int generate_result = 0;
6681 unsigned long lit = -1;
6685 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6686 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6687 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6689 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6691 if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6693 werror(W_POSSBUG2, __FILE__, __LINE__);
6694 DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
6695 fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6699 if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6701 operand *tmp = right ;
6706 if (AOP_TYPE(right) == AOP_LIT) {
6707 lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6710 if ( regsInCommon(left, result) || regsInCommon(right, result) )
6711 preserve_result = 1;
6713 if(result && AOP_SIZE(result))
6714 generate_result = 1;
6716 if(generate_result && !preserve_result)
6718 for(i = 0; i < AOP_SIZE(result); i++)
6719 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6722 for(i=0; i < AOP_SIZE(left); i++)
6724 if(AOP_TYPE(left) != AOP_ACC)
6727 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6729 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6731 if(is_LitOp(right)) {
6732 if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6733 pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6736 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6738 pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6743 if(generate_result && preserve_result)
6745 for(i = 0; i < AOP_SIZE(result); i++)
6746 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6750 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6752 if(generate_result && preserve_result)
6753 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6755 if(ifx && IC_TRUE(ifx))
6756 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6758 if(ifx && IC_FALSE(ifx))
6759 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6761 pic16_emitpLabel(falselbl->key);
6765 if(ifx && IC_FALSE(ifx))
6766 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6768 if(generate_result && preserve_result)
6770 for(i = 0; i < AOP_SIZE(result); i++)
6771 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6774 pic16_emitpLabel(donelbl->key);
6780 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6781 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6782 pic16_freeAsmop(result,NULL,ic,TRUE);
6788 // old version kept for reference
6790 /*-----------------------------------------------------------------*/
6791 /* genCmpEq - generates code for equal to */
6792 /*-----------------------------------------------------------------*/
6793 static void genCmpEq (iCode *ic, iCode *ifx)
6795 operand *left, *right, *result;
6796 unsigned long lit = 0L;
6798 symbol *falselbl = newiTempLabel(NULL);
6801 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6804 DEBUGpic16_emitcode ("; ifx is non-null","");
6806 DEBUGpic16_emitcode ("; ifx is null","");
6808 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6809 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6810 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6812 size = max(AOP_SIZE(left),AOP_SIZE(right));
6814 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6816 /* if literal, literal on the right or
6817 if the right is in a pointer register and left
6819 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
6820 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6821 operand *tmp = right ;
6827 if(ifx && !AOP_SIZE(result)){
6829 DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__);
6830 /* if they are both bit variables */
6831 if (AOP_TYPE(left) == AOP_CRY &&
6832 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6833 DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__);
6834 if(AOP_TYPE(right) == AOP_LIT){
6835 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6837 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6838 pic16_emitcode("cpl","c");
6839 } else if(lit == 1L) {
6840 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6842 pic16_emitcode("clr","c");
6844 /* AOP_TYPE(right) == AOP_CRY */
6846 symbol *lbl = newiTempLabel(NULL);
6847 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6848 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6849 pic16_emitcode("cpl","c");
6850 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6852 /* if true label then we jump if condition
6854 tlbl = newiTempLabel(NULL);
6855 if ( IC_TRUE(ifx) ) {
6856 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6857 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6859 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6860 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6862 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6865 /* left and right are both bit variables, result is carry */
6868 resolveIfx(&rIfx,ifx);
6870 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6871 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6872 pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6873 pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6878 DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__);
6880 /* They're not both bit variables. Is the right a literal? */
6881 if(AOP_TYPE(right) == AOP_LIT) {
6882 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6887 switch(lit & 0xff) {
6889 if ( IC_TRUE(ifx) ) {
6890 pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6892 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6894 pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6895 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6899 if ( IC_TRUE(ifx) ) {
6900 pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6902 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6904 pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6905 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6909 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6911 pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6916 /* end of size == 1 */
6920 genc16bit2lit(left,lit,offset);
6923 /* end of size == 2 */
6928 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6929 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6930 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6931 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6934 /* search for patterns that can be optimized */
6936 genc16bit2lit(left,lit,0);
6940 emitSKPZ; // if hi word unequal
6942 emitSKPNZ; // if hi word equal
6944 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6945 genc16bit2lit(left,lit,2);
6948 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6949 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6953 pic16_emitpLabel(falselbl->key);
6962 } else if(AOP_TYPE(right) == AOP_CRY ) {
6963 /* we know the left is not a bit, but that the right is */
6964 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6965 pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6966 pic16_popGet(AOP(right),offset));
6967 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6969 /* if the two are equal, then W will be 0 and the Z bit is set
6970 * we could test Z now, or go ahead and check the high order bytes if
6971 * the variable we're comparing is larger than a byte. */
6974 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6976 if ( IC_TRUE(ifx) ) {
6978 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6979 // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6982 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6983 // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6987 /* They're both variables that are larger than bits */
6990 tlbl = newiTempLabel(NULL);
6993 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6994 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6996 if ( IC_TRUE(ifx) ) {
7000 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7002 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7003 pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7007 DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7010 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7011 pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7016 DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7018 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7019 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7023 if(s>1 && IC_TRUE(ifx)) {
7024 pic16_emitpLabel(tlbl->key);
7025 pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7029 /* mark the icode as generated */
7034 /* if they are both bit variables */
7035 if (AOP_TYPE(left) == AOP_CRY &&
7036 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7037 DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__);
7038 if(AOP_TYPE(right) == AOP_LIT){
7039 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7041 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7042 pic16_emitcode("cpl","c");
7043 } else if(lit == 1L) {
7044 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7046 pic16_emitcode("clr","c");
7048 /* AOP_TYPE(right) == AOP_CRY */
7050 symbol *lbl = newiTempLabel(NULL);
7051 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7052 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7053 pic16_emitcode("cpl","c");
7054 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7057 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7058 pic16_outBitC(result);
7062 genIfxJump (ifx,"c");
7065 /* if the result is used in an arithmetic operation
7066 then put the result in place */
7067 pic16_outBitC(result);
7070 DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__);
7071 gencjne(left,right,result,ifx);
7074 gencjne(left,right,newiTempLabel(NULL));
7076 if(IC_TRUE(ifx)->key)
7077 gencjne(left,right,IC_TRUE(ifx)->key);
7079 gencjne(left,right,IC_FALSE(ifx)->key);
7083 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7084 pic16_aopPut(AOP(result),"a",0);
7089 genIfxJump (ifx,"a");
7093 /* if the result is used in an arithmetic operation
7094 then put the result in place */
7096 if (AOP_TYPE(result) != AOP_CRY)
7097 pic16_outAcc(result);
7099 /* leave the result in acc */
7103 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7104 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7105 pic16_freeAsmop(result,NULL,ic,TRUE);
7109 /*-----------------------------------------------------------------*/
7110 /* ifxForOp - returns the icode containing the ifx for operand */
7111 /*-----------------------------------------------------------------*/
7112 static iCode *ifxForOp ( operand *op, iCode *ic )
7116 /* if true symbol then needs to be assigned */
7117 if (IS_TRUE_SYMOP(op))
7120 /* if this has register type condition and
7121 the next instruction is ifx with the same operand
7122 and live to of the operand is upto the ifx only then */
7124 && ic->next->op == IFX
7125 && IC_COND(ic->next)->key == op->key
7126 && OP_SYMBOL(op)->liveTo <= ic->next->seq
7128 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7134 ic->next->op == IFX &&
7135 IC_COND(ic->next)->key == op->key) {
7136 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7141 DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7143 ic->next->op == IFX)
7144 DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7147 ic->next->op == IFX &&
7148 IC_COND(ic->next)->key == op->key) {
7149 DEBUGpic16_emitcode ("; "," key is okay");
7150 DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7151 OP_SYMBOL(op)->liveTo,
7156 /* the code below is completely untested
7157 * it just allows ulong2fs.c compile -- VR */
7160 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7161 __FILE__, __FUNCTION__, __LINE__);
7163 /* if this has register type condition and
7164 the next instruction is ifx with the same operand
7165 and live to of the operand is upto the ifx only then */
7167 ic->next->op == IFX &&
7168 IC_COND(ic->next)->key == op->key &&
7169 OP_SYMBOL(op)->liveTo <= ic->next->seq )
7173 ic->next->op == IFX &&
7174 IC_COND(ic->next)->key == op->key) {
7175 DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7179 fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7180 __FILE__, __FUNCTION__, __LINE__);
7182 // return ic->next->next; /* this just might work */ /* FIXME FIXME */
7187 /*-----------------------------------------------------------------*/
7188 /* genAndOp - for && operation */
7189 /*-----------------------------------------------------------------*/
7190 static void genAndOp (iCode *ic)
7192 operand *left,*right, *result;
7197 /* note here that && operations that are in an
7198 if statement are taken away by backPatchLabels
7199 only those used in arthmetic operations remain */
7200 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7201 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7202 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7204 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7206 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7207 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7208 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7210 /* if both are bit variables */
7211 /* if (AOP_TYPE(left) == AOP_CRY && */
7212 /* AOP_TYPE(right) == AOP_CRY ) { */
7213 /* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7214 /* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7215 /* pic16_outBitC(result); */
7217 /* tlbl = newiTempLabel(NULL); */
7218 /* pic16_toBoolean(left); */
7219 /* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7220 /* pic16_toBoolean(right); */
7221 /* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7222 /* pic16_outBitAcc(result); */
7225 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7226 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7227 pic16_freeAsmop(result,NULL,ic,TRUE);
7231 /*-----------------------------------------------------------------*/
7232 /* genOrOp - for || operation */
7233 /*-----------------------------------------------------------------*/
7236 modified this code, but it doesn't appear to ever get called
7239 static void genOrOp (iCode *ic)
7241 operand *left,*right, *result;
7246 /* note here that || operations that are in an
7247 if statement are taken away by backPatchLabels
7248 only those used in arthmetic operations remain */
7249 pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7250 pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7251 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7253 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7255 /* if both are bit variables */
7256 if (AOP_TYPE(left) == AOP_CRY &&
7257 AOP_TYPE(right) == AOP_CRY ) {
7258 pic16_emitcode("clrc","");
7259 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7260 AOP(left)->aopu.aop_dir,
7261 AOP(left)->aopu.aop_dir);
7262 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7263 AOP(right)->aopu.aop_dir,
7264 AOP(right)->aopu.aop_dir);
7265 pic16_emitcode("setc","");
7268 tlbl = newiTempLabel(NULL);
7269 pic16_toBoolean(left);
7271 pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7272 pic16_toBoolean(right);
7273 pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7275 pic16_outBitAcc(result);
7278 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7279 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7280 pic16_freeAsmop(result,NULL,ic,TRUE);
7283 /*-----------------------------------------------------------------*/
7284 /* isLiteralBit - test if lit == 2^n */
7285 /*-----------------------------------------------------------------*/
7286 static int isLiteralBit(unsigned long lit)
7288 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7289 0x100L,0x200L,0x400L,0x800L,
7290 0x1000L,0x2000L,0x4000L,0x8000L,
7291 0x10000L,0x20000L,0x40000L,0x80000L,
7292 0x100000L,0x200000L,0x400000L,0x800000L,
7293 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7294 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7297 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7298 for(idx = 0; idx < 32; idx++)
7304 /*-----------------------------------------------------------------*/
7305 /* continueIfTrue - */
7306 /*-----------------------------------------------------------------*/
7307 static void continueIfTrue (iCode *ic)
7311 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7315 /*-----------------------------------------------------------------*/
7317 /*-----------------------------------------------------------------*/
7318 static void jumpIfTrue (iCode *ic)
7322 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7326 /*-----------------------------------------------------------------*/
7327 /* jmpTrueOrFalse - */
7328 /*-----------------------------------------------------------------*/
7329 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7331 // ugly but optimized by peephole
7334 symbol *nlbl = newiTempLabel(NULL);
7335 pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7336 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7337 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7338 pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7340 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7341 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7346 /*-----------------------------------------------------------------*/
7347 /* genAnd - code for and */
7348 /*-----------------------------------------------------------------*/
7349 static void genAnd (iCode *ic, iCode *ifx)
7351 operand *left, *right, *result;
7353 unsigned long lit = 0L;
7359 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7360 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7361 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7363 resolveIfx(&rIfx,ifx);
7365 /* if left is a literal & right is not then exchange them */
7366 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7367 AOP_NEEDSACC(left)) {
7368 operand *tmp = right ;
7373 /* if result = right then exchange them */
7374 if(pic16_sameRegs(AOP(result),AOP(right))){
7375 operand *tmp = right ;
7380 /* if right is bit then exchange them */
7381 if (AOP_TYPE(right) == AOP_CRY &&
7382 AOP_TYPE(left) != AOP_CRY){
7383 operand *tmp = right ;
7387 if(AOP_TYPE(right) == AOP_LIT)
7388 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7390 size = AOP_SIZE(result);
7392 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7395 // result = bit & yy;
7396 if (AOP_TYPE(left) == AOP_CRY){
7397 // c = bit & literal;
7398 if(AOP_TYPE(right) == AOP_LIT){
7400 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7403 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7406 if(size && (AOP_TYPE(result) == AOP_CRY)){
7407 pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7410 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7414 pic16_emitcode("clr","c");
7417 if (AOP_TYPE(right) == AOP_CRY){
7419 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7420 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7423 MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7425 pic16_emitcode("rrc","a");
7426 pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7432 pic16_outBitC(result);
7434 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7435 genIfxJump(ifx, "c");
7439 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7440 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7441 if((AOP_TYPE(right) == AOP_LIT) &&
7442 (AOP_TYPE(result) == AOP_CRY) &&
7443 (AOP_TYPE(left) != AOP_CRY)){
7444 int posbit = isLiteralBit(lit);
7448 //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7451 pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7457 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7458 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7460 pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7461 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7464 DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7465 size = AOP_SIZE(left);
7468 int bp = posbit, ofs=0;
7475 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7476 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7480 pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7481 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7483 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7490 symbol *tlbl = newiTempLabel(NULL);
7491 int sizel = AOP_SIZE(left);
7497 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7499 /* patch provided by Aaron Colwell */
7500 if((posbit = isLiteralBit(bytelit)) != 0) {
7501 pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7502 pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7503 (posbit-1),0, PO_GPR_REGISTER));
7505 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7506 // pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7508 if (bytelit == 0xff) {
7509 /* Aaron had a MOVF instruction here, changed to MOVFW cause
7510 * a peephole could optimize it out -- VR */
7511 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7513 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7514 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7517 pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7518 pic16_popGetLabel(tlbl->key));
7522 /* old code, left here for reference -- VR 09/2004 */
7523 MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7525 if((posbit = isLiteralBit(bytelit)) != 0)
7526 pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7528 if(bytelit != 0x0FFL)
7529 pic16_emitcode("anl","a,%s",
7530 pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7531 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7537 // bit = left & literal
7540 pic16_emitpLabel(tlbl->key);
7542 // if(left & literal)
7545 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7548 pic16_emitpLabel(tlbl->key);
7553 pic16_outBitC(result);
7557 /* if left is same as result */
7558 if(pic16_sameRegs(AOP(result),AOP(left))){
7560 for(;size--; offset++,lit>>=8) {
7561 if(AOP_TYPE(right) == AOP_LIT){
7562 switch(lit & 0xff) {
7564 /* and'ing with 0 has clears the result */
7565 // pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7566 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7569 /* and'ing with 0xff is a nop when the result and left are the same */
7574 int p = pic16_my_powof2( (~lit) & 0xff );
7576 /* only one bit is set in the literal, so use a bcf instruction */
7577 // pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7578 pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7581 pic16_emitcode("movlw","0x%x", (lit & 0xff));
7582 pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7583 if(know_W != (lit&0xff))
7584 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7586 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7591 if (AOP_TYPE(left) == AOP_ACC) {
7592 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7594 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7595 pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7602 // left & result in different registers
7603 if(AOP_TYPE(result) == AOP_CRY){
7605 // if(size), result in bit
7606 // if(!size && ifx), conditional oper: if(left & right)
7607 symbol *tlbl = newiTempLabel(NULL);
7608 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7610 pic16_emitcode("setb","c");
7612 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7613 pic16_emitcode("anl","a,%s",
7614 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7615 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7620 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7621 pic16_outBitC(result);
7623 jmpTrueOrFalse(ifx, tlbl);
7625 for(;(size--);offset++) {
7627 // result = left & right
7628 if(AOP_TYPE(right) == AOP_LIT){
7629 int t = (lit >> (offset*8)) & 0x0FFL;
7632 pic16_emitcode("clrf","%s",
7633 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7634 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7637 pic16_emitcode("movf","%s,w",
7638 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7639 pic16_emitcode("movwf","%s",
7640 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7641 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7642 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7645 pic16_emitcode("movlw","0x%x",t);
7646 pic16_emitcode("andwf","%s,w",
7647 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7648 pic16_emitcode("movwf","%s",
7649 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7651 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7652 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7653 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7658 if (AOP_TYPE(left) == AOP_ACC) {
7659 pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7660 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7662 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7663 pic16_emitcode("andwf","%s,w",
7664 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7665 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7666 pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7668 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7669 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7675 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7676 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7677 pic16_freeAsmop(result,NULL,ic,TRUE);
7680 /*-----------------------------------------------------------------*/
7681 /* genOr - code for or */
7682 /*-----------------------------------------------------------------*/
7683 static void genOr (iCode *ic, iCode *ifx)
7685 operand *left, *right, *result;
7687 unsigned long lit = 0L;
7689 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7691 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7692 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7693 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7695 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7697 /* if left is a literal & right is not then exchange them */
7698 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7699 AOP_NEEDSACC(left)) {
7700 operand *tmp = right ;
7705 /* if result = right then exchange them */
7706 if(pic16_sameRegs(AOP(result),AOP(right))){
7707 operand *tmp = right ;
7712 /* if right is bit then exchange them */
7713 if (AOP_TYPE(right) == AOP_CRY &&
7714 AOP_TYPE(left) != AOP_CRY){
7715 operand *tmp = right ;
7720 DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7722 if(AOP_TYPE(right) == AOP_LIT)
7723 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7725 size = AOP_SIZE(result);
7729 if (AOP_TYPE(left) == AOP_CRY){
7730 if(AOP_TYPE(right) == AOP_LIT){
7731 // c = bit & literal;
7733 // lit != 0 => result = 1
7734 if(AOP_TYPE(result) == AOP_CRY){
7736 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7737 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7738 // AOP(result)->aopu.aop_dir,
7739 // AOP(result)->aopu.aop_dir);
7741 continueIfTrue(ifx);
7745 // lit == 0 => result = left
7746 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7748 pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7751 if (AOP_TYPE(right) == AOP_CRY){
7752 if(pic16_sameRegs(AOP(result),AOP(left))){
7754 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7755 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7756 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7758 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7759 AOP(result)->aopu.aop_dir,
7760 AOP(result)->aopu.aop_dir);
7761 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7762 AOP(right)->aopu.aop_dir,
7763 AOP(right)->aopu.aop_dir);
7764 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7765 AOP(result)->aopu.aop_dir,
7766 AOP(result)->aopu.aop_dir);
7768 if( AOP_TYPE(result) == AOP_ACC) {
7769 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7770 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7771 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7772 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7776 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7777 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7778 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7779 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7781 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7782 AOP(result)->aopu.aop_dir,
7783 AOP(result)->aopu.aop_dir);
7784 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7785 AOP(right)->aopu.aop_dir,
7786 AOP(right)->aopu.aop_dir);
7787 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7788 AOP(left)->aopu.aop_dir,
7789 AOP(left)->aopu.aop_dir);
7790 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7791 AOP(result)->aopu.aop_dir,
7792 AOP(result)->aopu.aop_dir);
7797 symbol *tlbl = newiTempLabel(NULL);
7798 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7801 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
7802 if( AOP_TYPE(right) == AOP_ACC) {
7803 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7805 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7806 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7811 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7812 pic16_emitcode(";XXX setb","c");
7813 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7814 AOP(left)->aopu.aop_dir,tlbl->key+100);
7815 pic16_toBoolean(right);
7816 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7817 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7818 jmpTrueOrFalse(ifx, tlbl);
7822 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7829 pic16_outBitC(result);
7831 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7832 genIfxJump(ifx, "c");
7836 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7837 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7838 if((AOP_TYPE(right) == AOP_LIT) &&
7839 (AOP_TYPE(result) == AOP_CRY) &&
7840 (AOP_TYPE(left) != AOP_CRY)){
7842 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7845 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7847 continueIfTrue(ifx);
7850 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7851 // lit = 0, result = boolean(left)
7853 pic16_emitcode(";XXX setb","c");
7854 pic16_toBoolean(right);
7856 symbol *tlbl = newiTempLabel(NULL);
7857 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7859 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7861 genIfxJump (ifx,"a");
7865 pic16_outBitC(result);
7869 /* if left is same as result */
7870 if(pic16_sameRegs(AOP(result),AOP(left))){
7872 for(;size--; offset++,lit>>=8) {
7873 if(AOP_TYPE(right) == AOP_LIT){
7874 if((lit & 0xff) == 0)
7875 /* or'ing with 0 has no effect */
7878 int p = pic16_my_powof2(lit & 0xff);
7880 /* only one bit is set in the literal, so use a bsf instruction */
7881 pic16_emitpcode(POC_BSF,
7882 pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7884 if(know_W != (lit & 0xff))
7885 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7886 know_W = lit & 0xff;
7887 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7892 if (AOP_TYPE(left) == AOP_ACC) {
7893 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset));
7894 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7896 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7897 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7899 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7900 pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7906 // left & result in different registers
7907 if(AOP_TYPE(result) == AOP_CRY){
7909 // if(size), result in bit
7910 // if(!size && ifx), conditional oper: if(left | right)
7911 symbol *tlbl = newiTempLabel(NULL);
7912 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7913 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7917 pic16_emitcode(";XXX setb","c");
7919 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7920 pic16_emitcode(";XXX orl","a,%s",
7921 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7922 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7927 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7928 pic16_outBitC(result);
7930 jmpTrueOrFalse(ifx, tlbl);
7931 } else for(;(size--);offset++){
7933 // result = left & right
7934 if(AOP_TYPE(right) == AOP_LIT){
7935 int t = (lit >> (offset*8)) & 0x0FFL;
7938 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
7939 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7941 pic16_emitcode("movf","%s,w",
7942 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7943 pic16_emitcode("movwf","%s",
7944 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7947 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7948 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7949 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7951 pic16_emitcode("movlw","0x%x",t);
7952 pic16_emitcode("iorwf","%s,w",
7953 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7954 pic16_emitcode("movwf","%s",
7955 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7961 // faster than result <- left, anl result,right
7962 // and better if result is SFR
7963 if (AOP_TYPE(left) == AOP_ACC) {
7964 pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset));
7965 pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7967 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
7968 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset));
7970 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7971 pic16_emitcode("iorwf","%s,w",
7972 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7974 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7975 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7980 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7981 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7982 pic16_freeAsmop(result,NULL,ic,TRUE);
7985 /*-----------------------------------------------------------------*/
7986 /* genXor - code for xclusive or */
7987 /*-----------------------------------------------------------------*/
7988 static void genXor (iCode *ic, iCode *ifx)
7990 operand *left, *right, *result;
7992 unsigned long lit = 0L;
7994 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7996 pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7997 pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7998 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8000 /* if left is a literal & right is not ||
8001 if left needs acc & right does not */
8002 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8003 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8004 operand *tmp = right ;
8009 /* if result = right then exchange them */
8010 if(pic16_sameRegs(AOP(result),AOP(right))){
8011 operand *tmp = right ;
8016 /* if right is bit then exchange them */
8017 if (AOP_TYPE(right) == AOP_CRY &&
8018 AOP_TYPE(left) != AOP_CRY){
8019 operand *tmp = right ;
8023 if(AOP_TYPE(right) == AOP_LIT)
8024 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8026 size = AOP_SIZE(result);
8030 if (AOP_TYPE(left) == AOP_CRY){
8031 if(AOP_TYPE(right) == AOP_LIT){
8032 // c = bit & literal;
8034 // lit>>1 != 0 => result = 1
8035 if(AOP_TYPE(result) == AOP_CRY){
8037 {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset));
8038 pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8040 continueIfTrue(ifx);
8043 pic16_emitcode("setb","c");
8047 // lit == 0, result = left
8048 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8050 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8052 // lit == 1, result = not(left)
8053 if(size && pic16_sameRegs(AOP(result),AOP(left))){
8054 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset));
8055 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset));
8056 pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8059 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8060 pic16_emitcode("cpl","c");
8067 symbol *tlbl = newiTempLabel(NULL);
8068 if (AOP_TYPE(right) == AOP_CRY){
8070 pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8073 int sizer = AOP_SIZE(right);
8075 // if val>>1 != 0, result = 1
8076 pic16_emitcode("setb","c");
8078 MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8080 // test the msb of the lsb
8081 pic16_emitcode("anl","a,#0xfe");
8082 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8086 pic16_emitcode("rrc","a");
8088 pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8089 pic16_emitcode("cpl","c");
8090 pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8095 pic16_outBitC(result);
8097 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8098 genIfxJump(ifx, "c");
8102 if(pic16_sameRegs(AOP(result),AOP(left))){
8103 /* if left is same as result */
8104 for(;size--; offset++) {
8105 if(AOP_TYPE(right) == AOP_LIT){
8106 int t = (lit >> (offset*8)) & 0x0FFL;
8110 if (IS_AOP_PREG(left)) {
8111 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8112 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8113 pic16_aopPut(AOP(result),"a",offset);
8115 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8116 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8117 pic16_emitcode("xrl","%s,%s",
8118 pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8119 pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8122 if (AOP_TYPE(left) == AOP_ACC)
8123 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8125 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8126 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8128 if (IS_AOP_PREG(left)) {
8129 pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8130 pic16_aopPut(AOP(result),"a",offset);
8132 pic16_emitcode("xrl","%s,a",
8133 pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8139 // left & result in different registers
8140 if(AOP_TYPE(result) == AOP_CRY){
8142 // if(size), result in bit
8143 // if(!size && ifx), conditional oper: if(left ^ right)
8144 symbol *tlbl = newiTempLabel(NULL);
8145 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8147 pic16_emitcode("setb","c");
8149 if((AOP_TYPE(right) == AOP_LIT) &&
8150 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8151 MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8153 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8154 pic16_emitcode("xrl","a,%s",
8155 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8157 pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8162 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8163 pic16_outBitC(result);
8165 jmpTrueOrFalse(ifx, tlbl);
8166 } else for(;(size--);offset++){
8168 // result = left & right
8169 if(AOP_TYPE(right) == AOP_LIT){
8170 int t = (lit >> (offset*8)) & 0x0FFL;
8173 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8174 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8175 pic16_emitcode("movf","%s,w",
8176 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8177 pic16_emitcode("movwf","%s",
8178 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8181 pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8182 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8183 pic16_emitcode("comf","%s,w",
8184 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8185 pic16_emitcode("movwf","%s",
8186 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8189 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8190 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8191 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8192 pic16_emitcode("movlw","0x%x",t);
8193 pic16_emitcode("xorwf","%s,w",
8194 pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8195 pic16_emitcode("movwf","%s",
8196 pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8202 // faster than result <- left, anl result,right
8203 // and better if result is SFR
8204 if (AOP_TYPE(left) == AOP_ACC) {
8205 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8206 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8208 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8209 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8210 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8211 pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8213 if ( AOP_TYPE(result) != AOP_ACC){
8214 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8215 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8221 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8222 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8223 pic16_freeAsmop(result,NULL,ic,TRUE);
8226 /*-----------------------------------------------------------------*/
8227 /* genInline - write the inline code out */
8228 /*-----------------------------------------------------------------*/
8229 static void genInline (iCode *ic)
8231 char *buffer, *bp, *bp1;
8233 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8235 _G.inLine += (!options.asmpeep);
8237 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8238 strcpy(buffer,IC_INLINE(ic));
8240 while((bp1=strstr(bp, "\\n"))) {
8248 /* This is an experimental code for #pragma inline
8249 and is temporarily disabled for 2.5.0 release */
8257 cbuf = Safe_strdup(buffer);
8258 cblen = strlen(buffer)+1;
8259 memset(cbuf, 0, cblen);
8264 if(*bp != '%')*bp1++ = *bp++;
8270 if(i>elementsInSet(asmInlineMap))break;
8273 s = indexSet(asmInlineMap, i);
8274 DEBUGpc("searching symbol s = `%s'", s);
8275 sym = findSym(SymbolTab, NULL, s);
8278 strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8280 strcat(bp1, sym->rname);
8286 if(strlen(bp1) > cblen - 16) {
8287 int i = strlen(cbuf);
8289 cbuf = realloc(cbuf, cblen);
8290 memset(cbuf+i, 0, 50);
8296 buffer = Safe_strdup( cbuf );
8303 /* emit each line as a code */
8309 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8317 /* print label, use this special format with NULL directive
8318 * to denote that the argument should not be indented with tab */
8319 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8326 if ((bp1 != bp) && *bp1)
8327 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8332 _G.inLine -= (!options.asmpeep);
8335 /*-----------------------------------------------------------------*/
8336 /* genRRC - rotate right with carry */
8337 /*-----------------------------------------------------------------*/
8338 static void genRRC (iCode *ic)
8340 operand *left , *result ;
8341 int size, offset = 0, same;
8343 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8345 /* rotate right with carry */
8347 result=IC_RESULT(ic);
8348 pic16_aopOp (left,ic,FALSE);
8349 pic16_aopOp (result,ic,TRUE);
8351 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8353 same = pic16_sameRegs(AOP(result),AOP(left));
8355 size = AOP_SIZE(result);
8357 DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8359 /* get the lsb and put it into the carry */
8360 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8367 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8369 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8370 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8376 pic16_freeAsmop(left,NULL,ic,TRUE);
8377 pic16_freeAsmop(result,NULL,ic,TRUE);
8380 /*-----------------------------------------------------------------*/
8381 /* genRLC - generate code for rotate left with carry */
8382 /*-----------------------------------------------------------------*/
8383 static void genRLC (iCode *ic)
8385 operand *left , *result ;
8386 int size, offset = 0;
8389 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8390 /* rotate right with carry */
8392 result=IC_RESULT(ic);
8393 pic16_aopOp (left,ic,FALSE);
8394 pic16_aopOp (result,ic,TRUE);
8396 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8398 same = pic16_sameRegs(AOP(result),AOP(left));
8400 /* move it to the result */
8401 size = AOP_SIZE(result);
8403 /* get the msb and put it into the carry */
8404 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8411 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8413 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8414 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8421 pic16_freeAsmop(left,NULL,ic,TRUE);
8422 pic16_freeAsmop(result,NULL,ic,TRUE);
8426 /* gpasm can get the highest order bit with HIGH/UPPER
8427 * so the following probably is not needed -- VR */
8429 /*-----------------------------------------------------------------*/
8430 /* genGetHbit - generates code get highest order bit */
8431 /*-----------------------------------------------------------------*/
8432 static void genGetHbit (iCode *ic)
8434 operand *left, *result;
8436 result=IC_RESULT(ic);
8437 pic16_aopOp (left,ic,FALSE);
8438 pic16_aopOp (result,ic,FALSE);
8440 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8441 /* get the highest order byte into a */
8442 MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8443 if(AOP_TYPE(result) == AOP_CRY){
8444 pic16_emitcode("rlc","a");
8445 pic16_outBitC(result);
8448 pic16_emitcode("rl","a");
8449 pic16_emitcode("anl","a,#0x01");
8450 pic16_outAcc(result);
8454 pic16_freeAsmop(left,NULL,ic,TRUE);
8455 pic16_freeAsmop(result,NULL,ic,TRUE);
8459 /*-----------------------------------------------------------------*/
8460 /* AccRol - rotate left accumulator by known count */
8461 /*-----------------------------------------------------------------*/
8462 static void AccRol (int shCount)
8464 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8465 shCount &= 0x0007; // shCount : 0..7
8470 pic16_emitcode("rl","a");
8473 pic16_emitcode("rl","a");
8474 pic16_emitcode("rl","a");
8477 pic16_emitcode("swap","a");
8478 pic16_emitcode("rr","a");
8481 pic16_emitcode("swap","a");
8484 pic16_emitcode("swap","a");
8485 pic16_emitcode("rl","a");
8488 pic16_emitcode("rr","a");
8489 pic16_emitcode("rr","a");
8492 pic16_emitcode("rr","a");
8498 /*-----------------------------------------------------------------*/
8499 /* AccLsh - left shift accumulator by known count */
8500 /*-----------------------------------------------------------------*/
8501 static void AccLsh (int shCount)
8503 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8509 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8512 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8513 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8516 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8517 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8520 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8523 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8524 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8527 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8528 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8531 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8535 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8538 /*-----------------------------------------------------------------*/
8539 /* AccRsh - right shift accumulator by known count */
8540 /*-----------------------------------------------------------------*/
8541 static void AccRsh (int shCount, int andmask)
8543 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8548 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8551 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8552 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8555 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8556 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8559 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8562 pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8563 pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8566 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8567 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8570 pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8575 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8577 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8581 /*-----------------------------------------------------------------*/
8582 /* AccSRsh - signed right shift accumulator by known count */
8583 /*-----------------------------------------------------------------*/
8584 static void AccSRsh (int shCount)
8587 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8590 pic16_emitcode("mov","c,acc.7");
8591 pic16_emitcode("rrc","a");
8592 } else if(shCount == 2){
8593 pic16_emitcode("mov","c,acc.7");
8594 pic16_emitcode("rrc","a");
8595 pic16_emitcode("mov","c,acc.7");
8596 pic16_emitcode("rrc","a");
8598 tlbl = newiTempLabel(NULL);
8599 /* rotate right accumulator */
8600 AccRol(8 - shCount);
8601 /* and kill the higher order bits */
8602 pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8603 pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8604 pic16_emitcode("orl","a,#0x%02x",
8605 (unsigned char)~SRMask[shCount]);
8606 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8612 /*-----------------------------------------------------------------*/
8613 /* shiftR1Left2Result - shift right one byte from left to result */
8614 /*-----------------------------------------------------------------*/
8615 static void shiftR1Left2ResultSigned (operand *left, int offl,
8616 operand *result, int offr,
8621 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8623 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8627 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8629 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8631 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8632 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8638 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8640 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8642 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8643 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8645 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8646 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8652 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8654 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8655 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8658 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8659 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8660 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8662 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8663 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8665 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8669 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8670 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8671 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8672 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0));
8673 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8677 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8679 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8680 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8682 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8683 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
8684 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8685 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8));
8686 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8691 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8692 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8693 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8694 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8695 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8696 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8698 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8699 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8700 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8701 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8702 pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8708 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8709 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8710 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8711 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8713 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8714 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8715 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr));
8723 /*-----------------------------------------------------------------*/
8724 /* shiftR1Left2Result - shift right one byte from left to result */
8725 /*-----------------------------------------------------------------*/
8726 static void shiftR1Left2Result (operand *left, int offl,
8727 operand *result, int offr,
8728 int shCount, int sign)
8732 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8734 same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8736 /* Copy the msb into the carry if signed. */
8738 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8748 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8750 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8751 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8757 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8759 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8760 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8763 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8768 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8770 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8771 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8774 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr));
8775 //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8776 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8777 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8781 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8782 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8783 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8787 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8788 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8789 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8791 pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8796 pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl));
8797 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8798 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8799 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8800 pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr));
8805 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8806 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8807 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8816 /*-----------------------------------------------------------------*/
8817 /* shiftL1Left2Result - shift left one byte from left to result */
8818 /*-----------------------------------------------------------------*/
8819 static void shiftL1Left2Result (operand *left, int offl,
8820 operand *result, int offr, int shCount)
8825 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8827 same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8828 DEBUGpic16_emitcode ("; ***","same = %d",same);
8829 // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8831 /* shift left accumulator */
8832 //AccLsh(shCount); // don't comment out just yet...
8833 // pic16_aopPut(AOP(result),"a",offr);
8837 /* Shift left 1 bit position */
8838 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8840 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8842 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8843 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8847 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8848 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8849 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8850 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8853 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8854 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8855 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8856 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8857 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8860 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8861 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8862 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8865 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8866 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8867 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8868 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8871 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8872 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8873 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8874 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8875 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8878 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8879 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8880 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8884 DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8889 /*-----------------------------------------------------------------*/
8890 /* movLeft2Result - move byte from left to result */
8891 /*-----------------------------------------------------------------*/
8892 static void movLeft2Result (operand *left, int offl,
8893 operand *result, int offr)
8896 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8897 if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8898 l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8900 if (*l == '@' && (IS_AOP_PREG(result))) {
8901 pic16_emitcode("mov","a,%s",l);
8902 pic16_aopPut(AOP(result),"a",offr);
8904 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8905 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8910 /*-----------------------------------------------------------------*/
8911 /* shiftL2Left2Result - shift left two bytes from left to result */
8912 /*-----------------------------------------------------------------*/
8913 static void shiftL2Left2Result (operand *left, int offl,
8914 operand *result, int offr, int shCount)
8916 int same = pic16_sameRegs(AOP(result), AOP(left));
8919 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8921 if (same && (offl != offr)) { // shift bytes
8924 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8925 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8927 } else { // just treat as different later on
8940 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8941 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8942 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8946 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8947 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8953 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8954 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8955 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8956 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8957 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8958 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8959 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8961 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8962 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8966 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8967 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8968 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8969 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8970 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8971 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8972 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8973 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8974 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8975 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8978 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8979 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8980 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8981 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8982 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8992 /* note, use a mov/add for the shift since the mov has a
8993 chance of getting optimized out */
8994 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8995 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8996 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8997 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8998 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9002 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9003 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9009 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9010 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9011 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9012 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9013 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9014 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9015 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9016 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9020 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9021 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9025 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9026 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9027 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9028 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9030 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9031 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9032 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9033 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9034 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9035 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9036 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9037 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9040 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9041 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9042 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9043 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9044 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9049 /*-----------------------------------------------------------------*/
9050 /* shiftR2Left2Result - shift right two bytes from left to result */
9051 /*-----------------------------------------------------------------*/
9052 static void shiftR2Left2Result (operand *left, int offl,
9053 operand *result, int offr,
9054 int shCount, int sign)
9056 int same = pic16_sameRegs(AOP(result), AOP(left));
9058 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9060 if (same && (offl != offr)) { // shift right bytes
9063 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9064 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9066 } else { // just treat as different later on
9078 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9083 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9084 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9086 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9087 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9088 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9089 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9094 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9097 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9098 pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9105 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9106 pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9107 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9109 pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9110 pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9111 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9112 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9114 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9115 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9116 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9118 pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9119 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9120 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9121 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9122 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9126 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9127 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9131 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9132 pic16_emitpcode(POC_BTFSC,
9133 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9134 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9142 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9143 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9145 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9146 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9147 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9148 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9150 pic16_emitpcode(POC_BTFSC,
9151 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9152 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9154 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9155 pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9156 pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9157 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9159 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9160 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9161 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9162 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9163 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9164 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9165 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9166 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9168 pic16_emitpcode(POC_BTFSC,
9169 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9170 pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9172 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9173 //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9180 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9181 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9182 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9183 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9186 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9188 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9193 /*-----------------------------------------------------------------*/
9194 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9195 /*-----------------------------------------------------------------*/
9196 static void shiftLLeftOrResult (operand *left, int offl,
9197 operand *result, int offr, int shCount)
9199 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9201 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9202 /* shift left accumulator */
9204 /* or with result */
9205 /* back to result */
9206 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9209 /*-----------------------------------------------------------------*/
9210 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9211 /*-----------------------------------------------------------------*/
9212 static void shiftRLeftOrResult (operand *left, int offl,
9213 operand *result, int offr, int shCount)
9215 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9217 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9218 /* shift right accumulator */
9220 /* or with result */
9221 /* back to result */
9222 pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9225 /*-----------------------------------------------------------------*/
9226 /* genlshOne - left shift a one byte quantity by known count */
9227 /*-----------------------------------------------------------------*/
9228 static void genlshOne (operand *result, operand *left, int shCount)
9230 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9231 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9234 /*-----------------------------------------------------------------*/
9235 /* genlshTwo - left shift two bytes by known amount != 0 */
9236 /*-----------------------------------------------------------------*/
9237 static void genlshTwo (operand *result,operand *left, int shCount)
9241 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9242 size = pic16_getDataSize(result);
9244 /* if shCount >= 8 */
9250 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9252 movLeft2Result(left, LSB, result, MSB16);
9254 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9257 /* 1 <= shCount <= 7 */
9260 shiftL1Left2Result(left, LSB, result, LSB, shCount);
9262 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9266 /*-----------------------------------------------------------------*/
9267 /* shiftLLong - shift left one long from left to result */
9268 /* offr = LSB or MSB16 */
9269 /*-----------------------------------------------------------------*/
9270 static void shiftLLong (operand *left, operand *result, int offr )
9272 int size = AOP_SIZE(result);
9273 int same = pic16_sameRegs(AOP(left),AOP(result));
9276 DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9278 if (same && (offr == MSB16)) { //shift one byte
9279 for(i=size-1;i>=MSB16;i--) {
9280 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9281 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9284 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9287 if (size > LSB+offr ){
9289 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9291 pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9292 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9296 if(size > MSB16+offr){
9298 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9300 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9301 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9305 if(size > MSB24+offr){
9307 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9309 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9310 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9314 if(size > MSB32+offr){
9316 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9318 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9319 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9323 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9327 /*-----------------------------------------------------------------*/
9328 /* genlshFour - shift four byte by a known amount != 0 */
9329 /*-----------------------------------------------------------------*/
9330 static void genlshFour (operand *result, operand *left, int shCount)
9334 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9335 size = AOP_SIZE(result);
9337 /* if shifting more that 3 bytes */
9338 if (shCount >= 24 ) {
9341 /* lowest order of left goes to the highest
9342 order of the destination */
9343 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9345 movLeft2Result(left, LSB, result, MSB32);
9347 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9348 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9349 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9354 /* more than two bytes */
9355 else if ( shCount >= 16 ) {
9356 /* lower order two bytes goes to higher order two bytes */
9358 /* if some more remaining */
9360 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9362 movLeft2Result(left, MSB16, result, MSB32);
9363 movLeft2Result(left, LSB, result, MSB24);
9365 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9366 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9370 /* if more than 1 byte */
9371 else if ( shCount >= 8 ) {
9372 /* lower order three bytes goes to higher order three bytes */
9376 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9378 movLeft2Result(left, LSB, result, MSB16);
9380 else{ /* size = 4 */
9382 movLeft2Result(left, MSB24, result, MSB32);
9383 movLeft2Result(left, MSB16, result, MSB24);
9384 movLeft2Result(left, LSB, result, MSB16);
9385 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9387 else if(shCount == 1)
9388 shiftLLong(left, result, MSB16);
9390 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9391 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9392 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9393 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9398 /* 1 <= shCount <= 7 */
9399 else if(shCount <= 3)
9401 shiftLLong(left, result, LSB);
9402 while(--shCount >= 1)
9403 shiftLLong(result, result, LSB);
9405 /* 3 <= shCount <= 7, optimize */
9407 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9408 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9409 shiftL2Left2Result(left, LSB, result, LSB, shCount);
9413 /*-----------------------------------------------------------------*/
9414 /* genLeftShiftLiteral - left shifting by known count */
9415 /*-----------------------------------------------------------------*/
9416 void pic16_genLeftShiftLiteral (operand *left,
9421 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9425 DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9426 pic16_freeAsmop(right,NULL,ic,TRUE);
9428 pic16_aopOp(left,ic,FALSE);
9429 pic16_aopOp(result,ic,TRUE);
9431 size = getSize(operandType(result));
9434 pic16_emitcode("; shift left ","result %d, left %d",size,
9438 /* I suppose that the left size >= result size */
9441 movLeft2Result(left, size, result, size);
9445 else if(shCount >= (size * 8))
9447 pic16_aopPut(AOP(result),zero,size);
9451 genlshOne (result,left,shCount);
9456 genlshTwo (result,left,shCount);
9460 genlshFour (result,left,shCount);
9464 pic16_freeAsmop(left,NULL,ic,TRUE);
9465 pic16_freeAsmop(result,NULL,ic,TRUE);
9468 /*-----------------------------------------------------------------*
9469 * genMultiAsm - repeat assembly instruction for size of register.
9470 * if endian == 1, then the high byte (i.e base address + size of
9471 * register) is used first else the low byte is used first;
9472 *-----------------------------------------------------------------*/
9473 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9478 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9491 pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset));
9497 #if !(USE_GENERIC_SIGNED_SHIFT)
9498 /*-----------------------------------------------------------------*/
9499 /* genLeftShift - generates code for left shifting */
9500 /*-----------------------------------------------------------------*/
9501 static void genLeftShift (iCode *ic)
9503 operand *left,*right, *result;
9506 symbol *tlbl , *tlbl1;
9509 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9511 right = IC_RIGHT(ic);
9513 result = IC_RESULT(ic);
9515 pic16_aopOp(right,ic,FALSE);
9517 /* if the shift count is known then do it
9518 as efficiently as possible */
9519 if (AOP_TYPE(right) == AOP_LIT) {
9520 pic16_genLeftShiftLiteral (left,right,result,ic);
9524 /* shift count is unknown then we have to form
9525 * a loop. Get the loop count in WREG : Note: we take
9526 * only the lower order byte since shifting
9527 * more than 32 bits make no sense anyway, ( the
9528 * largest size of an object can be only 32 bits ) */
9530 pic16_aopOp(left,ic,FALSE);
9531 pic16_aopOp(result,ic,FALSE);
9533 /* now move the left to the result if they are not the
9534 * same, and if size > 1,
9535 * and if right is not same to result (!!!) -- VR */
9536 if (!pic16_sameRegs(AOP(left),AOP(result))
9537 && (AOP_SIZE(result) > 1)) {
9539 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9541 size = AOP_SIZE(result);
9546 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9547 if (*l == '@' && (IS_AOP_PREG(result))) {
9549 pic16_emitcode("mov","a,%s",l);
9550 pic16_aopPut(AOP(result),"a",offset);
9554 /* we don't know if left is a literal or a register, take care -- VR */
9555 pic16_mov2f(AOP(result), AOP(left), offset);
9561 size = AOP_SIZE(result);
9563 /* if it is only one byte then */
9565 if(optimized_for_speed) {
9566 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9567 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9568 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9569 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9570 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9571 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9572 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9573 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9574 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9575 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9576 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9577 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9580 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9582 tlbl = newiTempLabel(NULL);
9585 /* this is already done, why change it? */
9586 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9587 pic16_mov2f(AOP(result), AOP(left), 0);
9591 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9592 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9593 pic16_emitpLabel(tlbl->key);
9594 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9595 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9597 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9602 if (pic16_sameRegs(AOP(left),AOP(result))) {
9604 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9606 tlbl = newiTempLabel(NULL);
9607 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9608 genMultiAsm(POC_RRCF, result, size,1);
9609 pic16_emitpLabel(tlbl->key);
9610 genMultiAsm(POC_RLCF, result, size,0);
9611 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9613 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9617 //tlbl = newiTempLabel(NULL);
9619 //tlbl1 = newiTempLabel(NULL);
9621 //reAdjustPreg(AOP(result));
9623 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9624 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9625 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9627 //pic16_emitcode("add","a,acc");
9628 //pic16_aopPut(AOP(result),"a",offset++);
9630 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9632 // pic16_emitcode("rlc","a");
9633 // pic16_aopPut(AOP(result),"a",offset++);
9635 //reAdjustPreg(AOP(result));
9637 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9638 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9641 tlbl = newiTempLabel(NULL);
9642 tlbl1= newiTempLabel(NULL);
9644 size = AOP_SIZE(result);
9647 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9649 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9651 /* offset should be 0, 1 or 3 */
9653 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9655 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9657 pic16_emitpcode(POC_MOVWF, pctemp);
9660 pic16_emitpLabel(tlbl->key);
9663 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9665 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9667 pic16_emitpcode(POC_DECFSZ, pctemp);
9668 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9669 pic16_emitpLabel(tlbl1->key);
9671 pic16_popReleaseTempReg(pctemp,1);
9675 pic16_freeAsmop (right,NULL,ic,TRUE);
9676 pic16_freeAsmop(left,NULL,ic,TRUE);
9677 pic16_freeAsmop(result,NULL,ic,TRUE);
9683 #error old code (left here for reference)
9684 /*-----------------------------------------------------------------*/
9685 /* genLeftShift - generates code for left shifting */
9686 /*-----------------------------------------------------------------*/
9687 static void genLeftShift (iCode *ic)
9689 operand *left,*right, *result;
9692 symbol *tlbl , *tlbl1;
9695 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9697 right = IC_RIGHT(ic);
9699 result = IC_RESULT(ic);
9701 pic16_aopOp(right,ic,FALSE);
9703 /* if the shift count is known then do it
9704 as efficiently as possible */
9705 if (AOP_TYPE(right) == AOP_LIT) {
9706 pic16_genLeftShiftLiteral (left,right,result,ic);
9710 /* shift count is unknown then we have to form
9711 a loop get the loop count in B : Note: we take
9712 only the lower order byte since shifting
9713 more that 32 bits make no sense anyway, ( the
9714 largest size of an object can be only 32 bits ) */
9717 pic16_aopOp(left,ic,FALSE);
9718 pic16_aopOp(result,ic,FALSE);
9720 /* now move the left to the result if they are not the
9722 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
9723 AOP_SIZE(result) > 1) {
9725 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9727 size = AOP_SIZE(result);
9730 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9731 if (*l == '@' && (IS_AOP_PREG(result))) {
9733 pic16_emitcode("mov","a,%s",l);
9734 pic16_aopPut(AOP(result),"a",offset);
9737 /* we don't know if left is a literal or a register, take care -- VR */
9738 pic16_mov2f(AOP(result), AOP(left), offset);
9744 size = AOP_SIZE(result);
9746 /* if it is only one byte then */
9748 if(optimized_for_speed) {
9749 pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9750 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9751 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9752 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9753 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9754 pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9755 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9756 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0));
9757 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9758 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0));
9759 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9760 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
9763 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9765 tlbl = newiTempLabel(NULL);
9766 if (!pic16_sameRegs(AOP(left),AOP(result))) {
9767 pic16_mov2f(AOP(result), AOP(left), 0);
9769 // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
9770 // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9773 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9774 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
9775 pic16_emitpLabel(tlbl->key);
9776 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9777 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9779 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9784 if (pic16_sameRegs(AOP(left),AOP(result))) {
9786 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9788 tlbl = newiTempLabel(NULL);
9789 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
9790 genMultiAsm(POC_RRCF, result, size,1);
9791 pic16_emitpLabel(tlbl->key);
9792 genMultiAsm(POC_RLCF, result, size,0);
9793 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
9795 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9799 //tlbl = newiTempLabel(NULL);
9801 //tlbl1 = newiTempLabel(NULL);
9803 //reAdjustPreg(AOP(result));
9805 //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9806 //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9807 //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9809 //pic16_emitcode("add","a,acc");
9810 //pic16_aopPut(AOP(result),"a",offset++);
9812 // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9814 // pic16_emitcode("rlc","a");
9815 // pic16_aopPut(AOP(result),"a",offset++);
9817 //reAdjustPreg(AOP(result));
9819 //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9820 //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9823 tlbl = newiTempLabel(NULL);
9824 tlbl1= newiTempLabel(NULL);
9826 size = AOP_SIZE(result);
9829 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
9831 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9833 /* offset should be 0, 1 or 3 */
9835 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9837 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
9839 pic16_emitpcode(POC_MOVWF, pctemp);
9842 pic16_emitpLabel(tlbl->key);
9845 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
9847 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++));
9849 pic16_emitpcode(POC_DECFSZ, pctemp);
9850 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9851 pic16_emitpLabel(tlbl1->key);
9853 pic16_popReleaseTempReg(pctemp,1);
9857 pic16_freeAsmop (right,NULL,ic,TRUE);
9858 pic16_freeAsmop(left,NULL,ic,TRUE);
9859 pic16_freeAsmop(result,NULL,ic,TRUE);
9863 /*-----------------------------------------------------------------*/
9864 /* genrshOne - right shift a one byte quantity by known count */
9865 /*-----------------------------------------------------------------*/
9866 static void genrshOne (operand *result, operand *left,
9867 int shCount, int sign)
9869 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9870 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9873 /*-----------------------------------------------------------------*/
9874 /* genrshTwo - right shift two bytes by known amount != 0 */
9875 /*-----------------------------------------------------------------*/
9876 static void genrshTwo (operand *result,operand *left,
9877 int shCount, int sign)
9879 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9880 /* if shCount >= 8 */
9884 shiftR1Left2Result(left, MSB16, result, LSB,
9887 movLeft2Result(left, MSB16, result, LSB);
9889 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9892 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9893 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),MSB16));
9897 /* 1 <= shCount <= 7 */
9899 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
9902 /*-----------------------------------------------------------------*/
9903 /* shiftRLong - shift right one long from left to result */
9904 /* offl = LSB or MSB16 */
9905 /*-----------------------------------------------------------------*/
9906 static void shiftRLong (operand *left, int offl,
9907 operand *result, int sign)
9909 int size = AOP_SIZE(result);
9910 int same = pic16_sameRegs(AOP(left),AOP(result));
9912 DEBUGpic16_emitcode ("; ***","%s %d offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9914 if (same && (offl == MSB16)) { //shift one byte right
9915 for(i=MSB16;i<size;i++) {
9916 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9917 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9922 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9928 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9930 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9931 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9935 /* add sign of "a" */
9936 pic16_addSign(result, MSB32, sign);
9940 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9942 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9943 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9947 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9949 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9950 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9954 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9957 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9958 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9963 /*-----------------------------------------------------------------*/
9964 /* genrshFour - shift four byte by a known amount != 0 */
9965 /*-----------------------------------------------------------------*/
9966 static void genrshFour (operand *result, operand *left,
9967 int shCount, int sign)
9969 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
9970 /* if shifting more that 3 bytes */
9971 if(shCount >= 24 ) {
9974 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9976 movLeft2Result(left, MSB32, result, LSB);
9978 pic16_addSign(result, MSB16, sign);
9980 else if(shCount >= 16){
9983 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9985 movLeft2Result(left, MSB24, result, LSB);
9986 movLeft2Result(left, MSB32, result, MSB16);
9988 pic16_addSign(result, MSB24, sign);
9990 else if(shCount >= 8){
9993 shiftRLong(left, MSB16, result, sign);
9994 else if(shCount == 0){
9995 movLeft2Result(left, MSB16, result, LSB);
9996 movLeft2Result(left, MSB24, result, MSB16);
9997 movLeft2Result(left, MSB32, result, MSB24);
9998 pic16_addSign(result, MSB32, sign);
10000 else{ //shcount >= 2
10001 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10002 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10003 /* the last shift is signed */
10004 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10005 pic16_addSign(result, MSB32, sign);
10008 else{ /* 1 <= shCount <= 7 */
10010 shiftRLong(left, LSB, result, sign);
10012 shiftRLong(result, LSB, result, sign);
10015 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10016 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10017 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10022 /*-----------------------------------------------------------------*/
10023 /* genRightShiftLiteral - right shifting by known count */
10024 /*-----------------------------------------------------------------*/
10025 static void genRightShiftLiteral (operand *left,
10031 int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
10032 int lsize,res_size;
10034 pic16_freeAsmop(right,NULL,ic,TRUE);
10036 pic16_aopOp(left,ic,FALSE);
10037 pic16_aopOp(result,ic,TRUE);
10039 DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10042 pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10046 lsize = pic16_getDataSize(left);
10047 res_size = pic16_getDataSize(result);
10048 /* test the LEFT size !!! */
10050 /* I suppose that the left size >= result size */
10052 assert (res_size <= lsize);
10053 while (res_size--) {
10054 pic16_mov2f (AOP(result), AOP(left), res_size);
10058 else if(shCount >= (lsize * 8)){
10060 if(res_size == 1) {
10061 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10063 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10064 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10069 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10070 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10071 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10073 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10078 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10083 switch (res_size) {
10085 genrshOne (result,left,shCount,sign);
10089 genrshTwo (result,left,shCount,sign);
10093 genrshFour (result,left,shCount,sign);
10101 pic16_freeAsmop(left,NULL,ic,TRUE);
10102 pic16_freeAsmop(result,NULL,ic,TRUE);
10105 #if !(USE_GENERIC_SIGNED_SHIFT)
10106 /*-----------------------------------------------------------------*/
10107 /* genSignedRightShift - right shift of signed number */
10108 /*-----------------------------------------------------------------*/
10109 static void genSignedRightShift (iCode *ic)
10111 operand *right, *left, *result;
10114 symbol *tlbl, *tlbl1 ;
10117 //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10119 /* we do it the hard way put the shift count in b
10120 and loop thru preserving the sign */
10121 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10123 right = IC_RIGHT(ic);
10124 left = IC_LEFT(ic);
10125 result = IC_RESULT(ic);
10127 pic16_aopOp(right,ic,FALSE);
10128 pic16_aopOp(left,ic,FALSE);
10129 pic16_aopOp(result,ic,FALSE);
10132 if ( AOP_TYPE(right) == AOP_LIT) {
10133 genRightShiftLiteral (left,right,result,ic,1);
10136 /* shift count is unknown then we have to form
10137 a loop get the loop count in B : Note: we take
10138 only the lower order byte since shifting
10139 more that 32 bits make no sense anyway, ( the
10140 largest size of an object can be only 32 bits ) */
10142 //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10143 //pic16_emitcode("inc","b");
10144 //pic16_freeAsmop (right,NULL,ic,TRUE);
10145 //pic16_aopOp(left,ic,FALSE);
10146 //pic16_aopOp(result,ic,FALSE);
10148 /* now move the left to the result if they are not the
10150 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10151 AOP_SIZE(result) > 1) {
10153 size = AOP_SIZE(result);
10157 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10158 if (*l == '@' && IS_AOP_PREG(result)) {
10160 pic16_emitcode("mov","a,%s",l);
10161 pic16_aopPut(AOP(result),"a",offset);
10163 pic16_aopPut(AOP(result),l,offset);
10165 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset));
10166 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10172 /* mov the highest order bit to OVR */
10173 tlbl = newiTempLabel(NULL);
10174 tlbl1= newiTempLabel(NULL);
10176 size = AOP_SIZE(result);
10179 pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */
10181 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10183 /* offset should be 0, 1 or 3 */
10184 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10186 pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key));
10188 pic16_emitpcode(POC_MOVWF, pctemp);
10191 pic16_emitpLabel(tlbl->key);
10193 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset));
10194 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset));
10197 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset));
10200 pic16_emitpcode(POC_DECFSZ, pctemp);
10201 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10202 pic16_emitpLabel(tlbl1->key);
10204 pic16_popReleaseTempReg(pctemp,1);
10206 size = AOP_SIZE(result);
10208 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10209 pic16_emitcode("rlc","a");
10210 pic16_emitcode("mov","ov,c");
10211 /* if it is only one byte then */
10213 l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10215 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10216 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10217 pic16_emitcode("mov","c,ov");
10218 pic16_emitcode("rrc","a");
10219 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10220 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10221 pic16_aopPut(AOP(result),"a",0);
10225 reAdjustPreg(AOP(result));
10226 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10227 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10228 pic16_emitcode("mov","c,ov");
10230 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10232 pic16_emitcode("rrc","a");
10233 pic16_aopPut(AOP(result),"a",offset--);
10235 reAdjustPreg(AOP(result));
10236 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10237 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10242 pic16_freeAsmop(left,NULL,ic,TRUE);
10243 pic16_freeAsmop(result,NULL,ic,TRUE);
10244 pic16_freeAsmop(right,NULL,ic,TRUE);
10248 #if !(USE_GENERIC_SIGNED_SHIFT)
10249 #warning This implementation of genRightShift() is incomplete!
10250 /*-----------------------------------------------------------------*/
10251 /* genRightShift - generate code for right shifting */
10252 /*-----------------------------------------------------------------*/
10253 static void genRightShift (iCode *ic)
10255 operand *right, *left, *result;
10259 symbol *tlbl, *tlbl1 ;
10261 /* if signed then we do it the hard way preserve the
10262 sign bit moving it inwards */
10263 letype = getSpec(operandType(IC_LEFT(ic)));
10264 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10266 if (!SPEC_USIGN(letype)) {
10267 genSignedRightShift (ic);
10271 /* signed & unsigned types are treated the same : i.e. the
10272 signed is NOT propagated inwards : quoting from the
10273 ANSI - standard : "for E1 >> E2, is equivalent to division
10274 by 2**E2 if unsigned or if it has a non-negative value,
10275 otherwise the result is implementation defined ", MY definition
10276 is that the sign does not get propagated */
10278 right = IC_RIGHT(ic);
10279 left = IC_LEFT(ic);
10280 result = IC_RESULT(ic);
10282 pic16_aopOp(right,ic,FALSE);
10284 /* if the shift count is known then do it
10285 as efficiently as possible */
10286 if (AOP_TYPE(right) == AOP_LIT) {
10287 genRightShiftLiteral (left,right,result,ic, 0);
10291 /* shift count is unknown then we have to form
10292 a loop get the loop count in B : Note: we take
10293 only the lower order byte since shifting
10294 more that 32 bits make no sense anyway, ( the
10295 largest size of an object can be only 32 bits ) */
10297 pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10298 pic16_emitcode("inc","b");
10299 pic16_aopOp(left,ic,FALSE);
10300 pic16_aopOp(result,ic,FALSE);
10302 /* now move the left to the result if they are not the
10304 if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10305 AOP_SIZE(result) > 1) {
10307 size = AOP_SIZE(result);
10310 l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10311 if (*l == '@' && IS_AOP_PREG(result)) {
10313 pic16_emitcode("mov","a,%s",l);
10314 pic16_aopPut(AOP(result),"a",offset);
10316 pic16_aopPut(AOP(result),l,offset);
10321 tlbl = newiTempLabel(NULL);
10322 tlbl1= newiTempLabel(NULL);
10323 size = AOP_SIZE(result);
10326 /* if it is only one byte then */
10329 tlbl = newiTempLabel(NULL);
10330 if (!pic16_sameRegs(AOP(left),AOP(result))) {
10331 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
10332 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10335 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0));
10336 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
10337 pic16_emitpLabel(tlbl->key);
10338 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
10339 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1));
10341 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10346 reAdjustPreg(AOP(result));
10347 pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10348 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10351 l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10353 pic16_emitcode("rrc","a");
10354 pic16_aopPut(AOP(result),"a",offset--);
10356 reAdjustPreg(AOP(result));
10358 pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10359 pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10362 pic16_freeAsmop(left,NULL,ic,TRUE);
10363 pic16_freeAsmop (right,NULL,ic,TRUE);
10364 pic16_freeAsmop(result,NULL,ic,TRUE);
10368 #if (USE_GENERIC_SIGNED_SHIFT)
10369 /*-----------------------------------------------------------------*/
10370 /* genGenericShift - generates code for left or right shifting */
10371 /*-----------------------------------------------------------------*/
10372 static void genGenericShift (iCode *ic, int isShiftLeft) {
10373 operand *left,*right, *result;
10375 int sign, signedCount;
10376 symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10377 PIC_OPCODE pos_shift, neg_shift;
10381 right = IC_RIGHT(ic);
10382 left = IC_LEFT(ic);
10383 result = IC_RESULT(ic);
10385 pic16_aopOp(right,ic,FALSE);
10386 pic16_aopOp(left,ic,FALSE);
10387 pic16_aopOp(result,ic,TRUE);
10389 sign = !SPEC_USIGN(operandType (left));
10390 signedCount = !SPEC_USIGN(operandType (right));
10392 /* if the shift count is known then do it
10393 as efficiently as possible */
10394 if (AOP_TYPE(right) == AOP_LIT) {
10395 long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10396 if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10397 // we should modify right->aopu.aop_lit here!
10398 // Instead we use abs(shCount) in genXXXShiftLiteral()...
10399 // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10401 pic16_genLeftShiftLiteral (left,right,result,ic);
10403 genRightShiftLiteral (left,right,result,ic, sign);
10406 } // if (right is literal)
10408 /* shift count is unknown then we have to form a loop.
10409 * Note: we take only the lower order byte since shifting
10410 * more than 32 bits make no sense anyway, ( the
10411 * largest size of an object can be only 32 bits )
10412 * Note: we perform arithmetic shifts if the left operand is
10413 * signed and we do an (effective) right shift, i. e. we
10414 * shift in the sign bit from the left. */
10416 label_complete = newiTempLabel ( NULL );
10417 label_loop_pos = newiTempLabel ( NULL );
10418 label_loop_neg = NULL;
10419 label_negative = NULL;
10420 pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10421 neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10424 // additional labels needed
10425 label_loop_neg = newiTempLabel ( NULL );
10426 label_negative = newiTempLabel ( NULL );
10429 // copy source to result -- this will effectively truncate the left operand to the size of result!
10430 // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10431 // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10432 for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10433 pic16_mov2f (AOP(result),AOP(left), offset);
10436 // if result is longer than left, fill with zeros (or sign)
10437 if (AOP_SIZE(left) < AOP_SIZE(result)) {
10438 if (sign && AOP_SIZE(left) > 0) {
10439 // shift signed operand -- fill with sign
10440 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10441 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10442 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10443 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10444 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10447 // shift unsigned operand -- fill result with zeros
10448 for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10449 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10452 } // if (size mismatch)
10454 pic16_mov2w (AOP(right), 0);
10455 pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10456 if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10459 // perform a shift by one (shift count is positive)
10460 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10461 // 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])
10462 pic16_emitpLabel (label_loop_pos->key);
10464 if (sign && (pos_shift == POC_RRCF)) {
10465 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10468 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10469 pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10470 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10472 // perform a shift by one (shift count is positive)
10473 // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10474 // 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])
10475 // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10476 pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10478 pic16_emitpLabel (label_loop_pos->key);
10479 if (sign && (pos_shift == POC_RRCF)) {
10480 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10483 genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10484 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10485 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10486 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10490 pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10492 pic16_emitpLabel (label_negative->key);
10493 // perform a shift by -1 (shift count is negative)
10494 // 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)
10496 pic16_emitpLabel (label_loop_neg->key);
10497 if (sign && (neg_shift == POC_RRCF)) {
10498 pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10501 genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10502 //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10503 pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10504 pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10505 } // if (signedCount)
10507 pic16_emitpLabel (label_complete->key);
10510 pic16_freeAsmop (right,NULL,ic,TRUE);
10511 pic16_freeAsmop(left,NULL,ic,TRUE);
10512 pic16_freeAsmop(result,NULL,ic,TRUE);
10515 static void genLeftShift (iCode *ic) {
10516 genGenericShift (ic, 1);
10519 static void genRightShift (iCode *ic) {
10520 genGenericShift (ic, 0);
10525 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10526 void pic16_loadFSR0(operand *op, int lit)
10528 if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10529 pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10531 assert (!OP_SYMBOL(op)->remat);
10532 // set up FSR0 with address of result
10533 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10534 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10538 /*----------------------------------------------------------------*/
10539 /* pic16_derefPtr - move one byte from the location ptr points to */
10540 /* to WREG (doWrite == 0) or one byte from WREG */
10541 /* to the location ptr points to (doWrite != 0) */
10542 /*----------------------------------------------------------------*/
10543 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10548 if (!fsr0_setup || !*fsr0_setup)
10550 pic16_loadFSR0( ptr, 0 );
10551 if (fsr0_setup) *fsr0_setup = 1;
10554 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10556 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10560 if (AOP(ptr)->aopu.aop_reg[2]) {
10561 if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10562 // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10563 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10564 pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl)));
10565 pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(ptr),2));
10566 pic16_callGenericPointerRW(doWrite, 1);
10568 // data pointer (just 2 byte given)
10569 if (!fsr0_setup || !*fsr0_setup)
10571 pic16_loadFSR0( ptr, 0 );
10572 if (fsr0_setup) *fsr0_setup = 1;
10575 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10577 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10582 assert (0 && "invalid pointer type specified");
10587 /*-----------------------------------------------------------------*/
10588 /* genUnpackBits - generates code for unpacking bits */
10589 /*-----------------------------------------------------------------*/
10590 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10593 sym_link *etype, *letype;
10594 int blen=0, bstr=0;
10597 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10598 etype = getSpec(operandType(result));
10599 letype = getSpec(operandType(left));
10601 // if(IS_BITFIELD(etype)) {
10602 blen = SPEC_BLEN(etype);
10603 bstr = SPEC_BSTR(etype);
10606 lbstr = SPEC_BSTR( letype );
10609 if((blen == 1) && (bstr < 8)) {
10610 /* it is a single bit, so use the appropriate bit instructions */
10611 DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10613 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10615 // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10616 if(!IS_PTR(operandType(left))/* && OP_SYMBOL(left)->remat && (ptype == POINTER)*/) {
10617 /* workaround to reduce the extra lfsr instruction */
10618 pic16_emitpcode(POC_BTFSC,
10619 pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10621 pic16_loadFSR0 (left, 0);
10622 pic16_emitpcode(POC_BTFSC,
10623 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10626 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10628 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10634 /* the following call to pic16_loadFSR0 is temporary until
10635 * optimization to handle single bit assignments is added
10636 * to the function. Until then use the old safe way! -- VR */
10638 if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
10639 // access symbol directly
10640 pic16_mov2w (AOP(left), 0);
10642 pic16_derefPtr (left, ptype, 0, NULL);
10645 /* if we have bitdisplacement then it fits */
10646 /* into this byte completely or if length is */
10647 /* less than a byte */
10648 if ((shCnt = SPEC_BSTR(etype)) ||
10649 (SPEC_BLEN(etype) <= 8)) {
10651 /* shift right acc */
10654 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10655 (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10657 /* VR -- normally I would use the following, but since we use the hack,
10658 * to avoid the masking from AccRsh, why not mask it right now? */
10661 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10664 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10670 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10671 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10678 static void genDataPointerGet(operand *left,
10682 int size, offset = 0, leoffset=0 ;
10684 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10685 pic16_aopOp(result, ic, TRUE);
10689 size = AOP_SIZE(result);
10690 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10694 /* The following tests may save a redudant movff instruction when
10695 * accessing unions */
10697 /* if they are the same */
10698 if (operandsEqu (left, result)) {
10699 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10705 /* if they are the same registers */
10706 if (pic16_sameRegs(AOP(left),AOP(result))) {
10707 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10713 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10714 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10715 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10722 if ( AOP_TYPE(left) == AOP_PCODE) {
10723 fprintf(stderr,"genDataPointerGet %s, %d\n",
10724 AOP(left)->aopu.pcop->name,
10725 (AOP(left)->aopu.pcop->type == PO_DIR)?
10726 PCOR(AOP(left)->aopu.pcop)->instance:
10727 PCOI(AOP(left)->aopu.pcop)->offset);
10731 if(AOP(left)->aopu.pcop->type == PO_DIR)
10732 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10734 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10737 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10739 // pic16_DumpOp("(result)",result);
10740 if(is_LitAOp(AOP(result))) {
10741 pic16_mov2w(AOP(left), offset); // patch 8
10742 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10744 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10745 pic16_popGet(AOP(left), offset), //patch 8
10746 pic16_popGet(AOP(result), offset)));
10754 pic16_freeAsmop(result,NULL,ic,TRUE);
10759 /*-----------------------------------------------------------------*/
10760 /* genNearPointerGet - pic16_emitcode for near pointer fetch */
10761 /*-----------------------------------------------------------------*/
10762 static void genNearPointerGet (operand *left,
10766 // asmop *aop = NULL;
10767 //regs *preg = NULL ;
10768 sym_link *rtype, *retype;
10769 sym_link *ltype, *letype;
10773 rtype = operandType(result);
10774 retype= getSpec(rtype);
10775 ltype = operandType(left);
10776 letype= getSpec(ltype);
10778 pic16_aopOp(left,ic,FALSE);
10780 // pic16_DumpOp("(left)",left);
10781 // pic16_DumpOp("(result)",result);
10783 /* if left is rematerialisable and
10784 * result is not bit variable type and
10785 * the left is pointer to data space i.e
10786 * lower 128 bytes of space */
10788 if (AOP_TYPE(left) == AOP_PCODE
10789 && !IS_BITFIELD(retype)
10790 && DCL_TYPE(ltype) == POINTER) {
10792 genDataPointerGet (left,result,ic);
10793 pic16_freeAsmop(left, NULL, ic, TRUE);
10797 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10798 pic16_aopOp (result,ic,TRUE);
10800 DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10803 if(IS_BITFIELD( retype )
10804 && (SPEC_BLEN(operandType(result))==1)
10808 int bitstrt, bytestrt;
10810 /* if this is bitfield of size 1, see if we are checking the value
10811 * of a single bit in an if-statement,
10812 * if yes, then don't generate usual code, but execute the
10813 * genIfx directly -- VR */
10817 /* CHECK: if next iCode is IFX
10818 * and current result operand is nextic's conditional operand
10819 * and current result operand live ranges ends at nextic's key number
10821 if((nextic->op == IFX)
10822 && (result == IC_COND(nextic))
10823 && (OP_LIVETO(result) == nextic->seq)
10824 && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)"
10826 /* everything is ok then */
10827 /* find a way to optimize the genIfx iCode */
10829 bytestrt = SPEC_BSTR(operandType(result))/8;
10830 bitstrt = SPEC_BSTR(operandType(result))%8;
10832 jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10834 genIfxpCOpJump(nextic, jop);
10836 pic16_freeAsmop(left, NULL, ic, TRUE);
10837 pic16_freeAsmop(result, NULL, ic, TRUE);
10843 /* if bitfield then unpack the bits */
10844 if (IS_BITFIELD(letype))
10845 genUnpackBits (result, left, NULL, POINTER);
10847 /* we have can just get the values */
10848 int size = AOP_SIZE(result);
10851 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10853 pic16_loadFSR0( left, 0 );
10857 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10858 pic16_popGet(AOP(result), offset++)));
10860 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10861 pic16_popGet(AOP(result), offset++)));
10867 /* now some housekeeping stuff */
10869 /* we had to allocate for this iCode */
10870 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10871 pic16_freeAsmop(NULL,aop,ic,TRUE);
10873 /* we did not allocate which means left
10874 * already in a pointer register, then
10875 * if size > 0 && this could be used again
10876 * we have to point it back to where it
10878 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10879 if (AOP_SIZE(result) > 1
10880 && !OP_SYMBOL(left)->remat
10881 && ( OP_SYMBOL(left)->liveTo > ic->seq
10883 // int size = AOP_SIZE(result) - 1;
10885 // pic16_emitcode("dec","%s",rname);
10891 pic16_freeAsmop(left,NULL,ic,TRUE);
10892 pic16_freeAsmop(result,NULL,ic,TRUE);
10895 /*-----------------------------------------------------------------*/
10896 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch */
10897 /*-----------------------------------------------------------------*/
10898 static void genPagedPointerGet (operand *left,
10903 regs *preg = NULL ;
10905 sym_link *rtype, *retype;
10907 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10909 rtype = operandType(result);
10910 retype= getSpec(rtype);
10912 pic16_aopOp(left,ic,FALSE);
10914 /* if the value is already in a pointer register
10915 then don't need anything more */
10916 if (!AOP_INPREG(AOP(left))) {
10917 /* otherwise get a free pointer register */
10919 preg = getFreePtr(ic,&aop,FALSE);
10920 pic16_emitcode("mov","%s,%s",
10922 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10923 rname = preg->name ;
10925 rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10927 pic16_freeAsmop(left,NULL,ic,TRUE);
10928 pic16_aopOp (result,ic,TRUE);
10930 /* if bitfield then unpack the bits */
10931 if (IS_BITFIELD(retype))
10932 genUnpackBits (result,left,rname,PPOINTER);
10934 /* we have can just get the values */
10935 int size = AOP_SIZE(result);
10940 pic16_emitcode("movx","a,@%s",rname);
10941 pic16_aopPut(AOP(result),"a",offset);
10946 pic16_emitcode("inc","%s",rname);
10950 /* now some housekeeping stuff */
10952 /* we had to allocate for this iCode */
10953 pic16_freeAsmop(NULL,aop,ic,TRUE);
10955 /* we did not allocate which means left
10956 already in a pointer register, then
10957 if size > 0 && this could be used again
10958 we have to point it back to where it
10960 if (AOP_SIZE(result) > 1 &&
10961 !OP_SYMBOL(left)->remat &&
10962 ( OP_SYMBOL(left)->liveTo > ic->seq ||
10964 int size = AOP_SIZE(result) - 1;
10966 pic16_emitcode("dec","%s",rname);
10971 pic16_freeAsmop(result,NULL,ic,TRUE);
10976 /*-----------------------------------------------------------------*/
10977 /* genFarPointerGet - gget value from far space */
10978 /*-----------------------------------------------------------------*/
10979 static void genFarPointerGet (operand *left,
10980 operand *result, iCode *ic)
10983 sym_link *retype = getSpec(operandType(result));
10985 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
10987 pic16_aopOp(left,ic,FALSE);
10989 /* if the operand is already in dptr
10990 then we do nothing else we move the value to dptr */
10991 if (AOP_TYPE(left) != AOP_STR) {
10992 /* if this is remateriazable */
10993 if (AOP_TYPE(left) == AOP_IMMD)
10994 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10995 else { /* we need to get it byte by byte */
10996 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10997 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10998 if (options.model == MODEL_FLAT24)
11000 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11004 /* so dptr know contains the address */
11005 pic16_freeAsmop(left,NULL,ic,TRUE);
11006 pic16_aopOp(result,ic,TRUE);
11008 /* if bit then unpack */
11009 if (IS_BITFIELD(retype))
11010 genUnpackBits(result,left,"dptr",FPOINTER);
11012 size = AOP_SIZE(result);
11016 pic16_emitcode("movx","a,@dptr");
11017 pic16_aopPut(AOP(result),"a",offset++);
11019 pic16_emitcode("inc","dptr");
11023 pic16_freeAsmop(result,NULL,ic,TRUE);
11027 /*-----------------------------------------------------------------*/
11028 /* genCodePointerGet - get value from code space */
11029 /*-----------------------------------------------------------------*/
11030 static void genCodePointerGet (operand *left,
11031 operand *result, iCode *ic)
11034 sym_link *retype = getSpec(operandType(result));
11036 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11038 pic16_aopOp(left,ic,FALSE);
11040 /* if the operand is already in dptr
11041 then we do nothing else we move the value to dptr */
11042 if (AOP_TYPE(left) != AOP_STR) {
11043 /* if this is remateriazable */
11044 if (AOP_TYPE(left) == AOP_IMMD)
11045 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11046 else { /* we need to get it byte by byte */
11047 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11048 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11049 if (options.model == MODEL_FLAT24)
11051 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11055 /* so dptr know contains the address */
11056 pic16_freeAsmop(left,NULL,ic,TRUE);
11057 pic16_aopOp(result,ic,FALSE);
11059 /* if bit then unpack */
11060 if (IS_BITFIELD(retype))
11061 genUnpackBits(result,left,"dptr",CPOINTER);
11063 size = AOP_SIZE(result);
11067 pic16_emitcode("clr","a");
11068 pic16_emitcode("movc","a,@a+dptr");
11069 pic16_aopPut(AOP(result),"a",offset++);
11071 pic16_emitcode("inc","dptr");
11075 pic16_freeAsmop(result,NULL,ic,TRUE);
11080 /*-----------------------------------------------------------------*/
11081 /* genGenPointerGet - gget value from generic pointer space */
11082 /*-----------------------------------------------------------------*/
11083 static void genGenPointerGet (operand *left,
11084 operand *result, iCode *ic)
11086 int size, offset, lit;
11087 sym_link *retype = getSpec(operandType(result));
11089 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11090 pic16_aopOp(left,ic,FALSE);
11091 pic16_aopOp(result,ic,FALSE);
11092 size = AOP_SIZE(result);
11094 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11096 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11098 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11099 // load FSR0 from immediate
11100 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11102 // pic16_loadFSR0( left );
11107 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11109 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11116 else { /* we need to get it byte by byte */
11117 // set up FSR0 with address from left
11118 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11119 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11125 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11127 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11134 /* if bit then unpack */
11135 if (IS_BITFIELD(retype))
11136 genUnpackBits(result,left,"BAD",GPOINTER);
11139 pic16_freeAsmop(left,NULL,ic,TRUE);
11140 pic16_freeAsmop(result,NULL,ic,TRUE);
11146 /*-----------------------------------------------------------------*/
11147 /* genGenPointerGet - gget value from generic pointer space */
11148 /*-----------------------------------------------------------------*/
11149 static void genGenPointerGet (operand *left,
11150 operand *result, iCode *ic)
11152 int size, offset, lit;
11153 sym_link *letype = getSpec(operandType(left));
11155 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11156 pic16_aopOp(left,ic,FALSE);
11157 pic16_aopOp(result,ic,TRUE);
11158 size = AOP_SIZE(result);
11160 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11162 /* if bit then unpack */
11163 if (IS_BITFIELD(letype)) {
11164 genUnpackBits(result,left,"BAD",GPOINTER);
11168 if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11170 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11171 // load FSR0 from immediate
11172 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11174 werror(W_POSSBUG2, __FILE__, __LINE__);
11179 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11181 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11188 } else { /* we need to get it byte by byte */
11190 /* set up WREG:PRODL:FSR0L with address from left */
11191 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11192 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11193 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11195 pic16_callGenericPointerRW(0, size);
11197 assignResultValue(result, 1);
11203 pic16_freeAsmop(left,NULL,ic,TRUE);
11204 pic16_freeAsmop(result,NULL,ic,TRUE);
11207 /*-----------------------------------------------------------------*/
11208 /* genConstPointerGet - get value from const generic pointer space */
11209 /*-----------------------------------------------------------------*/
11210 static void genConstPointerGet (operand *left,
11211 operand *result, iCode *ic)
11213 //sym_link *retype = getSpec(operandType(result));
11214 // symbol *albl = newiTempLabel(NULL); // patch 15
11215 // symbol *blbl = newiTempLabel(NULL); //
11216 // PIC_OPCODE poc; // patch 15
11220 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11221 pic16_aopOp(left,ic,FALSE);
11222 pic16_aopOp(result,ic,TRUE);
11223 size = AOP_SIZE(result);
11225 DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11227 DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11229 // set up table pointer
11230 if( (AOP_TYPE(left) == AOP_PCODE)
11231 && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11232 || (AOP(left)->aopu.pcop->type == PO_DIR)))
11234 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11235 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11236 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11237 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11238 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11239 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11241 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11242 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11243 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11247 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11248 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11252 pic16_freeAsmop(left,NULL,ic,TRUE);
11253 pic16_freeAsmop(result,NULL,ic,TRUE);
11257 /*-----------------------------------------------------------------*/
11258 /* genPointerGet - generate code for pointer get */
11259 /*-----------------------------------------------------------------*/
11260 static void genPointerGet (iCode *ic)
11262 operand *left, *result ;
11263 sym_link *type, *etype;
11268 left = IC_LEFT(ic);
11269 result = IC_RESULT(ic) ;
11271 /* depending on the type of pointer we need to
11272 move it to the correct pointer register */
11273 type = operandType(left);
11274 etype = getSpec(type);
11277 if (IS_PTR_CONST(type))
11279 if (IS_CODEPTR(type))
11281 DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11283 /* if left is of type of pointer then it is simple */
11284 if (IS_PTR(type) && !IS_FUNC(type->next))
11285 p_type = DCL_TYPE(type);
11287 /* we have to go by the storage class */
11288 p_type = PTR_TYPE(SPEC_OCLS(etype));
11290 DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11292 if (SPEC_OCLS(etype)->codesp ) {
11293 DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11294 //p_type = CPOINTER ;
11296 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11297 DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11298 /*p_type = FPOINTER ;*/
11300 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11301 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11302 /* p_type = PPOINTER; */
11304 if (SPEC_OCLS(etype) == idata ) {
11305 DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11306 /* p_type = IPOINTER; */
11308 DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11309 /* p_type = POINTER ; */
11313 /* now that we have the pointer type we assign
11314 the pointer values */
11318 genNearPointerGet (left,result,ic);
11322 genPagedPointerGet(left,result,ic);
11326 genFarPointerGet (left,result,ic);
11330 genConstPointerGet (left,result,ic);
11331 //pic16_emitcodePointerGet (left,result,ic);
11336 if (IS_PTR_CONST(type))
11337 genConstPointerGet (left,result,ic);
11340 genGenPointerGet (left,result,ic);
11344 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11345 "genPointerGet: illegal pointer type");
11350 /*-----------------------------------------------------------------*/
11351 /* genPackBits - generates code for packed bit storage */
11352 /*-----------------------------------------------------------------*/
11353 static void genPackBits (sym_link *etype , operand *result,
11355 char *rname, int p_type)
11363 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11364 blen = SPEC_BLEN(etype);
11365 bstr = SPEC_BSTR(etype);
11367 retype = getSpec(operandType(right));
11369 if(AOP_TYPE(right) == AOP_LIT) {
11370 if((blen == 1) && (bstr < 8)) {
11372 /* it is a single bit, so use the appropriate bit instructions */
11374 DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11376 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11377 // pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11378 if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11379 /* workaround to reduce the extra lfsr instruction */
11381 pic16_emitpcode(POC_BSF,
11382 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11384 pic16_emitpcode(POC_BCF,
11385 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11388 pic16_loadFSR0(result, 0);
11390 pic16_emitpcode(POC_BSF,
11391 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11393 pic16_emitpcode(POC_BCF,
11394 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11400 /* move literal to W */
11401 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11404 if(IS_BITFIELD(retype)
11405 && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11409 rblen = SPEC_BLEN( retype );
11410 rbstr = SPEC_BSTR( retype );
11413 if(IS_BITFIELD(etype)) {
11414 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11415 pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11417 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11420 pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11422 if(IS_BITFIELD(etype)) {
11423 pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11425 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11428 pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11432 /* move right to W */
11433 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11436 /* if the bit length is less than or */
11437 /* it exactly fits a byte then */
11438 if((shCnt=SPEC_BSTR(etype))
11439 || SPEC_BLEN(etype) <= 8 ) {
11440 int fsr0_setup = 0;
11442 if (blen != 8 || bstr != 0) {
11443 // we need to combine the value with the old value
11444 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11446 DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11447 SPEC_BSTR(etype), SPEC_BLEN(etype));
11449 /* shift left acc */
11452 /* using PRODH as a temporary register here */
11453 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11455 if (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) {
11456 /* access symbol directly */
11457 pic16_mov2w (AOP(result), 0);
11459 /* get old value */
11460 pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11463 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11464 (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11465 (unsigned char)(0xff >> (8-bstr))) ));
11466 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11467 } // if (blen != 8 || bstr != 0)
11469 /* write new value back */
11470 if (IS_SYMOP(result) & !IS_PTR(operandType(result))) {
11471 pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11473 pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11482 fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11483 fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11488 pic16_loadFSR0(result, 0); // load FSR0 with address of result
11489 rLen = SPEC_BLEN(etype)-8;
11491 /* now generate for lengths greater than one byte */
11495 mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11501 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11507 pic16_emitcode("movx","@dptr,a");
11512 DEBUGpic16_emitcode(";lcall","__gptrput");
11520 pic16_mov2w(AOP(right), offset++);
11523 /* last last was not complete */
11525 /* save the byte & read byte */
11528 // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11529 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11534 pic16_emitcode ("mov","b,a");
11535 pic16_emitcode("movx","a,@dptr");
11539 pic16_emitcode ("push","b");
11540 pic16_emitcode ("push","acc");
11541 pic16_emitcode ("lcall","__gptrget");
11542 pic16_emitcode ("pop","b");
11548 DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11549 pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11550 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11551 // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11552 // pic16_emitcode ("orl","a,b");
11555 // if (p_type == GPOINTER)
11556 // pic16_emitcode("pop","b");
11561 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11562 // pic16_emitcode("mov","@%s,a",rname);
11566 pic16_emitcode("movx","@dptr,a");
11570 DEBUGpic16_emitcode(";lcall","__gptrput");
11577 // pic16_freeAsmop(right, NULL, ic, TRUE);
11579 /*-----------------------------------------------------------------*/
11580 /* genDataPointerSet - remat pointer to data space */
11581 /*-----------------------------------------------------------------*/
11582 static void genDataPointerSet(operand *right,
11586 int size, offset = 0, resoffset=0 ;
11588 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11589 pic16_aopOp(right,ic,FALSE);
11591 size = AOP_SIZE(right);
11593 // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11596 if ( AOP_TYPE(result) == AOP_PCODE) {
11597 fprintf(stderr,"genDataPointerSet %s, %d\n",
11598 AOP(result)->aopu.pcop->name,
11599 (AOP(result)->aopu.pcop->type == PO_DIR)?
11600 PCOR(AOP(result)->aopu.pcop)->instance:
11601 PCOI(AOP(result)->aopu.pcop)->offset);
11605 if(AOP(result)->aopu.pcop->type == PO_DIR)
11606 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11609 if (AOP_TYPE(right) == AOP_LIT) {
11612 if(!IS_FLOAT(operandType( right )))
11613 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11616 unsigned long lit_int;
11620 /* take care if literal is a float */
11621 info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11622 lit = info.lit_int;
11625 lit = lit >> (8*offset);
11627 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11628 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11630 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11633 pic16_mov2w(AOP(right), offset);
11634 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11640 pic16_freeAsmop(right,NULL,ic,TRUE);
11645 /*-----------------------------------------------------------------*/
11646 /* genNearPointerSet - pic16_emitcode for near pointer put */
11647 /*-----------------------------------------------------------------*/
11648 static void genNearPointerSet (operand *right,
11654 sym_link *ptype = operandType(result);
11655 sym_link *resetype;
11657 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11658 retype= getSpec(operandType(right));
11659 resetype = getSpec(operandType(result));
11661 pic16_aopOp(result,ic,FALSE);
11663 /* if the result is rematerializable &
11664 * in data space & not a bit variable */
11666 /* and result is not a bit variable */
11667 if (AOP_TYPE(result) == AOP_PCODE
11668 // && AOP_TYPE(result) == AOP_IMMD
11669 && DCL_TYPE(ptype) == POINTER
11670 && !IS_BITFIELD(retype)
11671 && !IS_BITFIELD(resetype)) {
11673 genDataPointerSet (right,result,ic);
11674 pic16_freeAsmop(result,NULL,ic,TRUE);
11678 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11679 pic16_aopOp(right,ic,FALSE);
11680 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11682 /* if bitfield then unpack the bits */
11683 if (IS_BITFIELD(resetype)) {
11684 genPackBits (resetype, result, right, NULL, POINTER);
11686 /* we have can just get the values */
11687 int size = AOP_SIZE(right);
11690 pic16_loadFSR0(result, 0);
11692 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11694 if (AOP_TYPE(right) == AOP_LIT) {
11695 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11697 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11699 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11701 } else { // no literal
11703 pic16_emitpcode(POC_MOVFF,
11704 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11705 pic16_popCopyReg(&pic16_pc_postinc0)));
11707 pic16_emitpcode(POC_MOVFF,
11708 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11709 pic16_popCopyReg(&pic16_pc_indf0)));
11716 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11717 /* now some housekeeping stuff */
11719 /* we had to allocate for this iCode */
11720 pic16_freeAsmop(NULL,aop,ic,TRUE);
11722 /* we did not allocate which means left
11723 * already in a pointer register, then
11724 * if size > 0 && this could be used again
11725 * we have to point it back to where it
11727 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11728 if (AOP_SIZE(right) > 1
11729 && !OP_SYMBOL(result)->remat
11730 && ( OP_SYMBOL(result)->liveTo > ic->seq
11733 int size = AOP_SIZE(right) - 1;
11736 pic16_emitcode("decf","fsr0,f");
11737 //pic16_emitcode("dec","%s",rname);
11741 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11744 pic16_freeAsmop(right,NULL,ic,TRUE);
11745 pic16_freeAsmop(result,NULL,ic,TRUE);
11748 /*-----------------------------------------------------------------*/
11749 /* genPagedPointerSet - pic16_emitcode for Paged pointer put */
11750 /*-----------------------------------------------------------------*/
11751 static void genPagedPointerSet (operand *right,
11756 regs *preg = NULL ;
11760 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11762 retype= getSpec(operandType(right));
11764 pic16_aopOp(result,ic,FALSE);
11766 /* if the value is already in a pointer register
11767 then don't need anything more */
11768 if (!AOP_INPREG(AOP(result))) {
11769 /* otherwise get a free pointer register */
11771 preg = getFreePtr(ic,&aop,FALSE);
11772 pic16_emitcode("mov","%s,%s",
11774 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11775 rname = preg->name ;
11777 rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11779 pic16_freeAsmop(result,NULL,ic,TRUE);
11780 pic16_aopOp (right,ic,FALSE);
11782 /* if bitfield then unpack the bits */
11783 if (IS_BITFIELD(retype))
11784 genPackBits (retype,result,right,rname,PPOINTER);
11786 /* we have can just get the values */
11787 int size = AOP_SIZE(right);
11791 l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11794 pic16_emitcode("movx","@%s,a",rname);
11797 pic16_emitcode("inc","%s",rname);
11803 /* now some housekeeping stuff */
11805 /* we had to allocate for this iCode */
11806 pic16_freeAsmop(NULL,aop,ic,TRUE);
11808 /* we did not allocate which means left
11809 already in a pointer register, then
11810 if size > 0 && this could be used again
11811 we have to point it back to where it
11813 if (AOP_SIZE(right) > 1 &&
11814 !OP_SYMBOL(result)->remat &&
11815 ( OP_SYMBOL(result)->liveTo > ic->seq ||
11817 int size = AOP_SIZE(right) - 1;
11819 pic16_emitcode("dec","%s",rname);
11824 pic16_freeAsmop(right,NULL,ic,TRUE);
11829 /*-----------------------------------------------------------------*/
11830 /* genFarPointerSet - set value from far space */
11831 /*-----------------------------------------------------------------*/
11832 static void genFarPointerSet (operand *right,
11833 operand *result, iCode *ic)
11836 sym_link *retype = getSpec(operandType(right));
11838 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11839 pic16_aopOp(result,ic,FALSE);
11841 /* if the operand is already in dptr
11842 then we do nothing else we move the value to dptr */
11843 if (AOP_TYPE(result) != AOP_STR) {
11844 /* if this is remateriazable */
11845 if (AOP_TYPE(result) == AOP_IMMD)
11846 pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11847 else { /* we need to get it byte by byte */
11848 pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11849 pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11850 if (options.model == MODEL_FLAT24)
11852 pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11856 /* so dptr know contains the address */
11857 pic16_freeAsmop(result,NULL,ic,TRUE);
11858 pic16_aopOp(right,ic,FALSE);
11860 /* if bit then unpack */
11861 if (IS_BITFIELD(retype))
11862 genPackBits(retype,result,right,"dptr",FPOINTER);
11864 size = AOP_SIZE(right);
11868 char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11870 pic16_emitcode("movx","@dptr,a");
11872 pic16_emitcode("inc","dptr");
11876 pic16_freeAsmop(right,NULL,ic,TRUE);
11879 /*-----------------------------------------------------------------*/
11880 /* genGenPointerSet - set value from generic pointer space */
11881 /*-----------------------------------------------------------------*/
11883 static void genGenPointerSet (operand *right,
11884 operand *result, iCode *ic)
11886 int i, size, offset, lit;
11887 sym_link *retype = getSpec(operandType(right));
11889 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11891 pic16_aopOp(result,ic,FALSE);
11892 pic16_aopOp(right,ic,FALSE);
11893 size = AOP_SIZE(right);
11896 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11898 /* if the operand is already in dptr
11899 then we do nothing else we move the value to dptr */
11900 if (AOP_TYPE(result) != AOP_STR) {
11901 /* if this is remateriazable */
11902 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11903 // WARNING: anythig until "else" is untested!
11904 if (AOP_TYPE(result) == AOP_IMMD) {
11905 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11906 lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11907 // load FSR0 from immediate
11908 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11912 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11914 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11920 else { /* we need to get it byte by byte */
11921 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11922 //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11924 // set up FSR0 with address of result
11925 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11926 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11928 /* hack hack! see if this the FSR. If so don't load W */
11929 if(AOP_TYPE(right) != AOP_ACC) {
11931 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11933 if(AOP_TYPE(right) == AOP_LIT)
11936 // note: pic16_popGet handles sign extension
11937 for(i=0;i<size;i++) {
11938 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11940 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11942 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11947 for(i=0;i<size;i++) {
11949 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11950 pic16_popCopyReg(&pic16_pc_postinc0)));
11952 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11953 pic16_popCopyReg(&pic16_pc_indf0)));
11959 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
11960 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11962 } // if (AOP_TYPE(result) != AOP_IMMD)
11964 } // if (AOP_TYPE(result) != AOP_STR)
11965 /* so dptr know contains the address */
11968 /* if bit then unpack */
11969 if (IS_BITFIELD(retype))
11970 genPackBits(retype,result,right,"dptr",GPOINTER);
11972 size = AOP_SIZE(right);
11975 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
11977 // set up FSR0 with address of result
11978 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11979 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11982 if (AOP_TYPE(right) == AOP_LIT) {
11983 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11985 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11987 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11989 } else { // no literal
11991 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11993 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12001 pic16_freeAsmop(right,NULL,ic,TRUE);
12002 pic16_freeAsmop(result,NULL,ic,TRUE);
12006 static void genGenPointerSet (operand *right,
12007 operand *result, iCode *ic)
12010 sym_link *retype = getSpec(operandType(result));
12012 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12014 pic16_aopOp(result,ic,FALSE);
12015 pic16_aopOp(right,ic,FALSE);
12016 size = AOP_SIZE(right);
12018 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12021 /* if bit then unpack */
12022 if (IS_BITFIELD(retype)) {
12023 // pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12024 genPackBits(retype,result,right,"dptr",GPOINTER);
12028 size = AOP_SIZE(right);
12030 DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size);
12033 /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12035 /* value of right+0 is placed on stack, which will be retrieved
12036 * by the support function this restoring the stack. The important
12037 * thing is that there is no need to manually restore stack pointer
12039 pushaop(AOP(right), 0);
12040 // mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12041 if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12042 if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12043 if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12045 /* load address to write to in WREG:FSR0H:FSR0L */
12046 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12047 pic16_popCopyReg(&pic16_pc_fsr0l)));
12048 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12049 pic16_popCopyReg(&pic16_pc_prodl)));
12050 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12052 pic16_callGenericPointerRW(1, size);
12055 pic16_freeAsmop(right,NULL,ic,TRUE);
12056 pic16_freeAsmop(result,NULL,ic,TRUE);
12059 /*-----------------------------------------------------------------*/
12060 /* genPointerSet - stores the value into a pointer location */
12061 /*-----------------------------------------------------------------*/
12062 static void genPointerSet (iCode *ic)
12064 operand *right, *result ;
12065 sym_link *type, *etype;
12070 right = IC_RIGHT(ic);
12071 result = IC_RESULT(ic) ;
12073 /* depending on the type of pointer we need to
12074 move it to the correct pointer register */
12075 type = operandType(result);
12076 etype = getSpec(type);
12078 /* if left is of type of pointer then it is simple */
12079 if (IS_PTR(type) && !IS_FUNC(type->next)) {
12080 p_type = DCL_TYPE(type);
12083 /* we have to go by the storage class */
12084 p_type = PTR_TYPE(SPEC_OCLS(etype));
12086 /* if (SPEC_OCLS(etype)->codesp ) { */
12087 /* p_type = CPOINTER ; */
12090 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12091 /* p_type = FPOINTER ; */
12093 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12094 /* p_type = PPOINTER ; */
12096 /* if (SPEC_OCLS(etype) == idata ) */
12097 /* p_type = IPOINTER ; */
12099 /* p_type = POINTER ; */
12102 /* now that we have the pointer type we assign
12103 the pointer values */
12107 genNearPointerSet (right,result,ic);
12111 genPagedPointerSet (right,result,ic);
12115 genFarPointerSet (right,result,ic);
12119 genGenPointerSet (right,result,ic);
12123 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12124 "genPointerSet: illegal pointer type");
12128 /*-----------------------------------------------------------------*/
12129 /* genIfx - generate code for Ifx statement */
12130 /*-----------------------------------------------------------------*/
12131 static void genIfx (iCode *ic, iCode *popIc)
12133 operand *cond = IC_COND(ic);
12138 pic16_aopOp(cond,ic,FALSE);
12140 /* get the value into acc */
12141 if (AOP_TYPE(cond) != AOP_CRY)
12142 pic16_toBoolean(cond);
12145 /* the result is now in the accumulator */
12146 pic16_freeAsmop(cond,NULL,ic,TRUE);
12148 /* if there was something to be popped then do it */
12152 /* if the condition is a bit variable */
12153 if (isbit && IS_ITEMP(cond) &&
12155 genIfxJump(ic,"c");
12156 DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12158 if (isbit && !IS_ITEMP(cond))
12159 genIfxJump(ic,OP_SYMBOL(cond)->rname);
12161 genIfxJump(ic,"a");
12166 /*-----------------------------------------------------------------*/
12167 /* genAddrOf - generates code for address of */
12168 /*-----------------------------------------------------------------*/
12169 static void genAddrOf (iCode *ic)
12171 operand *result, *left;
12173 symbol *sym; // = OP_SYMBOL(IC_LEFT(ic));
12174 pCodeOp *pcop0, *pcop1, *pcop2;
12178 pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12180 sym = OP_SYMBOL( IC_LEFT(ic) );
12183 /* get address of symbol on stack */
12184 DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12186 fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12187 OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12190 // operands on stack are accessible via "FSR2 + index" with index
12191 // starting at 2 for arguments and growing from 0 downwards for
12192 // local variables (index == 0 is not assigned so we add one here)
12194 int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12196 assert (soffs < 0);
12199 DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12200 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12201 pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12202 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12203 pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12204 pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12205 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12211 // if(pic16_debug_verbose) {
12212 // fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12213 // __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12216 pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12217 size = AOP_SIZE(IC_RESULT(ic));
12219 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12220 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12221 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12224 pic16_emitpcode(POC_MOVLW, pcop0);
12225 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12226 pic16_emitpcode(POC_MOVLW, pcop1);
12227 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12228 pic16_emitpcode(POC_MOVLW, pcop2);
12229 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12232 pic16_emitpcode(POC_MOVLW, pcop0);
12233 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12234 pic16_emitpcode(POC_MOVLW, pcop1);
12235 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12237 pic16_emitpcode(POC_MOVLW, pcop0);
12238 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12241 pic16_freeAsmop(left, NULL, ic, FALSE);
12243 pic16_freeAsmop(result,NULL,ic,TRUE);
12248 /*-----------------------------------------------------------------*/
12249 /* genFarFarAssign - assignment when both are in far space */
12250 /*-----------------------------------------------------------------*/
12251 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12253 int size = AOP_SIZE(right);
12256 /* first push the right side on to the stack */
12258 l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12260 pic16_emitcode ("push","acc");
12263 pic16_freeAsmop(right,NULL,ic,FALSE);
12264 /* now assign DPTR to result */
12265 pic16_aopOp(result,ic,FALSE);
12266 size = AOP_SIZE(result);
12268 pic16_emitcode ("pop","acc");
12269 pic16_aopPut(AOP(result),"a",--offset);
12271 pic16_freeAsmop(result,NULL,ic,FALSE);
12276 /*-----------------------------------------------------------------*/
12277 /* genAssign - generate code for assignment */
12278 /*-----------------------------------------------------------------*/
12279 static void genAssign (iCode *ic)
12281 operand *result, *right;
12282 int size, offset,know_W;
12283 unsigned long lit = 0L;
12285 result = IC_RESULT(ic);
12286 right = IC_RIGHT(ic) ;
12290 /* if they are the same */
12291 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12294 /* reversed order operands are aopOp'ed so that result operand
12295 * is effective in case right is a stack symbol. This maneauver
12296 * allows to use the _G.resDirect flag later */
12297 pic16_aopOp(result,ic,TRUE);
12298 pic16_aopOp(right,ic,FALSE);
12300 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12302 /* if they are the same registers */
12303 if (pic16_sameRegs(AOP(right),AOP(result)))
12306 /* if the result is a bit */
12307 if (AOP_TYPE(result) == AOP_CRY) {
12308 /* if the right size is a literal then
12309 we know what the value is */
12310 if (AOP_TYPE(right) == AOP_LIT) {
12312 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12313 pic16_popGet(AOP(result),0));
12315 if (((int) operandLitValue(right)))
12316 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12317 AOP(result)->aopu.aop_dir,
12318 AOP(result)->aopu.aop_dir);
12320 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12321 AOP(result)->aopu.aop_dir,
12322 AOP(result)->aopu.aop_dir);
12326 /* the right is also a bit variable */
12327 if (AOP_TYPE(right) == AOP_CRY) {
12328 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12329 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12330 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12332 pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12333 AOP(result)->aopu.aop_dir,
12334 AOP(result)->aopu.aop_dir);
12335 pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12336 AOP(right)->aopu.aop_dir,
12337 AOP(right)->aopu.aop_dir);
12338 pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12339 AOP(result)->aopu.aop_dir,
12340 AOP(result)->aopu.aop_dir);
12344 /* we need to or */
12345 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12346 pic16_toBoolean(right);
12348 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12349 //pic16_aopPut(AOP(result),"a",0);
12353 /* bit variables done */
12355 size = AOP_SIZE(result);
12358 if(AOP_TYPE(right) == AOP_LIT) {
12359 if(!IS_FLOAT(operandType( right )))
12360 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12363 unsigned long lit_int;
12367 /* take care if literal is a float */
12368 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12369 lit = info.lit_int;
12373 // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12374 // sizeof(unsigned long int), sizeof(float));
12377 if (AOP_TYPE(right) == AOP_REG) {
12378 DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12380 pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12385 /* when do we have to read the program memory?
12386 * - if right itself is a symbol in code space
12387 * (we don't care what it points to if it's a pointer)
12388 * - AND right is not a function (we would want its address)
12390 if(AOP_TYPE(right) != AOP_LIT
12391 && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12392 && !IS_FUNC(OP_SYM_TYPE(right))
12393 && !IS_ITEMP(right))
12395 DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12396 fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12398 // set up table pointer
12399 if(is_LitOp(right)) {
12400 // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12401 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12402 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12403 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12404 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12405 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12406 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12408 // fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12409 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12410 pic16_popCopyReg(&pic16_pc_tblptrl)));
12411 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12412 pic16_popCopyReg(&pic16_pc_tblptrh)));
12413 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12414 pic16_popCopyReg(&pic16_pc_tblptru)));
12417 /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12418 size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12420 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12421 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12422 pic16_popGet(AOP(result),offset)));
12426 /* FIXME: for pointers we need to extend differently (according
12427 * to pointer type DATA/CODE/EEPROM/... :*/
12428 size = getSize(OP_SYM_TYPE(right));
12429 if(AOP_SIZE(result) > size) {
12430 size = AOP_SIZE(result) - size;
12432 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12442 /* VR - What is this?! */
12443 if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
12444 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12445 if(aopIdx(AOP(result),0) == 4) {
12447 /* this is a workaround to save value of right into wreg too,
12448 * value of wreg is going to be used later */
12449 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12450 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12451 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12455 DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__);
12461 DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
12462 if(AOP_TYPE(right) == AOP_LIT) {
12464 if(know_W != (lit&0xff))
12465 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12467 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12469 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12473 } else if (AOP_TYPE(right) == AOP_CRY) {
12474 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12476 //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12477 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12478 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12480 } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12481 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12482 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12484 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
12486 if(!_G.resDirect) /* use this aopForSym feature */
12487 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12494 pic16_freeAsmop (right,NULL,ic,FALSE);
12495 pic16_freeAsmop (result,NULL,ic,TRUE);
12498 /*-----------------------------------------------------------------*/
12499 /* genJumpTab - generates code for jump table */
12500 /*-----------------------------------------------------------------*/
12501 static void genJumpTab (iCode *ic)
12506 pCodeOp *jt_offs_hi;
12511 pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12512 /* get the condition into accumulator */
12513 l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12515 /* multiply by three */
12516 pic16_emitcode("add","a,acc");
12517 pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12519 jtab = newiTempLabel(NULL);
12520 pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12521 pic16_emitcode("jmp","@a+dptr");
12522 pic16_emitcode("","%05d_DS_:",jtab->key+100);
12525 pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12526 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12528 pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12529 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12530 pic16_emitpLabel(jtab->key);
12534 jt_offs = pic16_popGetTempReg(0);
12535 jt_offs_hi = pic16_popGetTempReg(1);
12536 jt_label = pic16_popGetLabel (jtab->key);
12537 //fprintf (stderr, "Creating jump table...\n");
12539 // calculate offset into jump table (idx * sizeof (GOTO))
12540 pic16_emitpcode(POC_CLRF , jt_offs_hi);
12541 pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12542 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12543 pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12544 pic16_emitpcode(POC_RLCF , jt_offs_hi);
12545 pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12546 pic16_emitpcode(POC_MOVWF , jt_offs);
12548 // prepare PCLATx (set to first entry in jump table)
12549 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12550 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12551 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12552 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12553 pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12555 // set PCLATx to selected entry (new PCL is stored in jt_offs)
12556 pic16_emitpcode(POC_ADDWF , jt_offs);
12557 pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12558 pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12560 pic16_emitpcode(POC_INCF , pic16_popCopyReg(&pic16_pc_pclatu));
12562 // release temporaries and prepare jump into table (new PCL --> WREG)
12563 pic16_emitpcode(POC_MOVFW , jt_offs);
12564 pic16_popReleaseTempReg (jt_offs_hi, 1);
12565 pic16_popReleaseTempReg (jt_offs, 0);
12567 // jump into the table
12568 pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12570 pic16_emitpLabelFORCE(jtab->key);
12573 pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12574 // pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12576 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12577 /* now generate the jump labels */
12578 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12579 jtab = setNextItem(IC_JTLABELS(ic))) {
12580 // pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12581 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12584 pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12588 /*-----------------------------------------------------------------*/
12589 /* genMixedOperation - gen code for operators between mixed types */
12590 /*-----------------------------------------------------------------*/
12592 TSD - Written for the PIC port - but this unfortunately is buggy.
12593 This routine is good in that it is able to efficiently promote
12594 types to different (larger) sizes. Unfortunately, the temporary
12595 variables that are optimized out by this routine are sometimes
12596 used in other places. So until I know how to really parse the
12597 iCode tree, I'm going to not be using this routine :(.
12599 static int genMixedOperation (iCode *ic)
12602 operand *result = IC_RESULT(ic);
12603 sym_link *ctype = operandType(IC_LEFT(ic));
12604 operand *right = IC_RIGHT(ic);
12610 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12612 pic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12618 nextright = IC_RIGHT(nextic);
12619 nextleft = IC_LEFT(nextic);
12620 nextresult = IC_RESULT(nextic);
12622 pic16_aopOp(right,ic,FALSE);
12623 pic16_aopOp(result,ic,FALSE);
12624 pic16_aopOp(nextright, nextic, FALSE);
12625 pic16_aopOp(nextleft, nextic, FALSE);
12626 pic16_aopOp(nextresult, nextic, FALSE);
12628 if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12630 operand *t = right;
12634 pic16_emitcode(";remove right +","");
12636 } else if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12638 operand *t = right;
12642 pic16_emitcode(";remove left +","");
12646 big = AOP_SIZE(nextleft);
12647 small = AOP_SIZE(nextright);
12649 switch(nextic->op) {
12652 pic16_emitcode(";optimize a +","");
12653 /* if unsigned or not an integral type */
12654 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12655 pic16_emitcode(";add a bit to something","");
12658 pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12660 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12661 pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12662 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12664 pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12672 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12673 pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12674 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12677 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12679 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12680 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12681 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12682 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12683 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12686 pic16_emitcode("rlf","known_zero,w");
12693 if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12694 pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12695 pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12697 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12707 pic16_freeAsmop(right,NULL,ic,TRUE);
12708 pic16_freeAsmop(result,NULL,ic,TRUE);
12709 pic16_freeAsmop(nextright,NULL,ic,TRUE);
12710 pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12712 nextic->generated = 1;
12719 /*-----------------------------------------------------------------*/
12720 /* genCast - gen code for casting */
12721 /*-----------------------------------------------------------------*/
12722 static void genCast (iCode *ic)
12724 operand *result = IC_RESULT(ic);
12725 sym_link *ctype = operandType(IC_LEFT(ic));
12726 sym_link *rtype = operandType(IC_RIGHT(ic));
12727 sym_link *restype = operandType(IC_RESULT(ic));
12728 operand *right = IC_RIGHT(ic);
12734 /* if they are equivalent then do nothing */
12735 // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12738 pic16_aopOp(result,ic,FALSE);
12739 pic16_aopOp(right,ic,FALSE) ;
12741 DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12744 /* if the result is a bit */
12745 if (AOP_TYPE(result) == AOP_CRY) {
12747 /* if the right size is a literal then
12748 * we know what the value is */
12749 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12751 if (AOP_TYPE(right) == AOP_LIT) {
12752 pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12753 pic16_popGet(AOP(result),0));
12755 if (((int) operandLitValue(right)))
12756 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12757 AOP(result)->aopu.aop_dir,
12758 AOP(result)->aopu.aop_dir);
12760 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12761 AOP(result)->aopu.aop_dir,
12762 AOP(result)->aopu.aop_dir);
12766 /* the right is also a bit variable */
12767 if (AOP_TYPE(right) == AOP_CRY) {
12769 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12771 pic16_emitcode("clrc","");
12772 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12773 AOP(right)->aopu.aop_dir,
12774 AOP(right)->aopu.aop_dir);
12775 pic16_aopPut(AOP(result),"c",0);
12779 /* we need to or */
12780 if (AOP_TYPE(right) == AOP_REG) {
12781 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0));
12782 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12783 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
12785 pic16_toBoolean(right);
12786 pic16_aopPut(AOP(result),"a",0);
12790 if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12793 size = AOP_SIZE(result);
12795 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12797 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
12798 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12799 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12802 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
12807 if(IS_BITFIELD(getSpec(restype))
12808 && IS_BITFIELD(getSpec(rtype))) {
12809 DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12812 /* if they are the same size : or less */
12813 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12815 /* if they are in the same place */
12816 if (pic16_sameRegs(AOP(right),AOP(result)))
12819 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
12821 if (IS_PTR_CONST(rtype))
12823 if (IS_CODEPTR(rtype))
12825 DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12828 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12830 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12832 DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12835 if(AOP_TYPE(right) == AOP_IMMD) {
12836 pCodeOp *pcop0, *pcop1, *pcop2;
12837 symbol *sym = OP_SYMBOL( right );
12839 size = AOP_SIZE(result);
12841 pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12843 pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12845 pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12848 pic16_emitpcode(POC_MOVLW, pcop0);
12849 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12850 pic16_emitpcode(POC_MOVLW, pcop1);
12851 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12852 pic16_emitpcode(POC_MOVLW, pcop2);
12853 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12856 pic16_emitpcode(POC_MOVLW, pcop0);
12857 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12858 pic16_emitpcode(POC_MOVLW, pcop1);
12859 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12861 pic16_emitpcode(POC_MOVLW, pcop0);
12862 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12866 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12867 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12868 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12869 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12870 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12871 if(AOP_SIZE(result) <2)
12872 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12874 /* if they in different places then copy */
12875 size = AOP_SIZE(result);
12878 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12879 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12886 /* if the result is of type pointer */
12887 if (IS_PTR(ctype)) {
12889 sym_link *type = operandType(right);
12890 sym_link *etype = getSpec(type);
12892 DEBUGpic16_emitcode("; ***","%s %d - pointer cast",__FUNCTION__,__LINE__);
12894 /* pointer to generic pointer */
12895 if (IS_GENPTR(ctype)) {
12899 p_type = DCL_TYPE(type);
12901 /* we have to go by the storage class */
12902 p_type = PTR_TYPE(SPEC_OCLS(etype));
12904 /* if (SPEC_OCLS(etype)->codesp ) */
12905 /* p_type = CPOINTER ; */
12907 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12908 /* p_type = FPOINTER ; */
12910 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12911 /* p_type = PPOINTER; */
12913 /* if (SPEC_OCLS(etype) == idata ) */
12914 /* p_type = IPOINTER ; */
12916 /* p_type = POINTER ; */
12919 /* the first two bytes are known */
12920 DEBUGpic16_emitcode("; ***","%s %d - pointer cast2",__FUNCTION__,__LINE__);
12921 size = GPTRSIZE - 1;
12924 if(offset < AOP_SIZE(right)) {
12925 DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12926 pic16_mov2f(AOP(result), AOP(right), offset);
12928 if ((AOP_TYPE(right) == AOP_PCODE) &&
12929 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12930 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12931 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12934 pic16_aopPut(AOP(result),
12935 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12940 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12943 /* the last byte depending on type */
12947 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12948 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12949 // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12953 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12957 pic16_emitcode(";BUG!? ","%d",__LINE__);
12961 pic16_emitcode(";BUG!? ","%d",__LINE__);
12966 if (GPTRSIZE > AOP_SIZE(right)) {
12967 // assume data pointer... THIS MIGHT BE WRONG!
12968 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12969 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12971 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12976 /* this should never happen */
12977 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12978 "got unknown pointer type");
12981 //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
12987 /* just copy the pointers */
12988 size = AOP_SIZE(result);
12991 pic16_aopPut(AOP(result),
12992 pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13001 /* so we now know that the size of destination is greater
13002 than the size of the source.
13003 Now, if the next iCode is an operator then we might be
13004 able to optimize the operation without performing a cast.
13006 if(genMixedOperation(ic))
13009 DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
13011 /* we move to result for the size of source */
13012 size = AOP_SIZE(right);
13017 pic16_mov2f(AOP(result), AOP(right), offset);
13021 /* now depending on the sign of the destination */
13022 size = AOP_SIZE(result) - AOP_SIZE(right);
13023 /* if unsigned or not an integral type */
13024 if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13026 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset++));
13028 /* we need to extend the sign :( */
13031 /* Save one instruction of casting char to int */
13032 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
13033 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13034 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
13036 pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13039 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13041 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13043 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
13046 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset++));
13051 pic16_freeAsmop(right,NULL,ic,TRUE);
13052 pic16_freeAsmop(result,NULL,ic,TRUE);
13056 /*-----------------------------------------------------------------*/
13057 /* genDjnz - generate decrement & jump if not zero instrucion */
13058 /*-----------------------------------------------------------------*/
13059 static int genDjnz (iCode *ic, iCode *ifx)
13061 symbol *lbl, *lbl1;
13062 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
13067 /* if the if condition has a false label
13068 then we cannot save */
13072 /* if the minus is not of the form
13074 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13075 !IS_OP_LITERAL(IC_RIGHT(ic)))
13078 if (operandLitValue(IC_RIGHT(ic)) != 1)
13081 /* if the size of this greater than one then no
13083 if (getSize(operandType(IC_RESULT(ic))) > 1)
13086 /* otherwise we can save BIG */
13087 lbl = newiTempLabel(NULL);
13088 lbl1= newiTempLabel(NULL);
13090 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13092 if (IS_AOP_PREG(IC_RESULT(ic))) {
13093 pic16_emitcode("dec","%s",
13094 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13095 pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13096 pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13100 pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13101 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13103 pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13104 pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13108 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13109 ifx->generated = 1;
13113 /*-----------------------------------------------------------------*/
13114 /* genReceive - generate code for a receive iCode */
13115 /*-----------------------------------------------------------------*/
13116 static void genReceive (iCode *ic)
13122 fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13123 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13125 // pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13127 if (isOperandInFarSpace(IC_RESULT(ic))
13128 && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13129 || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13131 int size = getSize(operandType(IC_RESULT(ic)));
13132 int offset = pic16_fReturnSizePic - size;
13136 pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13137 fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13141 DEBUGpic16_emitcode ("; ***","1 %s %d",__FUNCTION__,__LINE__);
13143 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13144 size = AOP_SIZE(IC_RESULT(ic));
13147 pic16_emitcode ("pop","acc");
13148 pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13151 DEBUGpic16_emitcode ("; ***","2 %s %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13153 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13156 /* set pseudo stack pointer to where it should be - dw*/
13157 GpsuedoStkPtr = ic->parmBytes;
13159 /* setting GpsuedoStkPtr has side effects here: */
13160 assignResultValue(IC_RESULT(ic), 0);
13163 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13166 /*-----------------------------------------------------------------*/
13167 /* genDummyRead - generate code for dummy read of volatiles */
13168 /*-----------------------------------------------------------------*/
13170 genDummyRead (iCode * ic)
13176 if (op && IS_SYMOP(op)) {
13177 if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13178 fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13181 pic16_aopOp (op, ic, FALSE);
13182 for (i=0; i < AOP_SIZE(op); i++) {
13183 // may need to protect this from the peepholer -- this is not nice but works...
13184 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13185 pic16_mov2w (AOP(op),i);
13186 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13188 pic16_freeAsmop (op, NULL, ic, TRUE);
13190 fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13194 /*-----------------------------------------------------------------*/
13195 /* genpic16Code - generate code for pic16 based controllers */
13196 /*-----------------------------------------------------------------*/
13198 * At this point, ralloc.c has gone through the iCode and attempted
13199 * to optimize in a way suitable for a PIC. Now we've got to generate
13200 * PIC instructions that correspond to the iCode.
13202 * Once the instructions are generated, we'll pass through both the
13203 * peep hole optimizer and the pCode optimizer.
13204 *-----------------------------------------------------------------*/
13206 void genpic16Code (iCode *lic)
13211 lineHead = lineCurr = NULL;
13213 pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13214 pic16_addpBlock(pb);
13217 /* if debug information required */
13218 if (options.debug && currFunc) {
13220 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13225 for (ic = lic ; ic ; ic = ic->next ) {
13227 DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13228 if ( cln != ic->lineno ) {
13229 if ( options.debug ) {
13230 debugFile->writeCLine (ic);
13233 if(!options.noCcodeInAsm) {
13234 pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13235 printCLine(ic->filename, ic->lineno)));
13241 if(options.iCodeInAsm) {
13244 /* insert here code to print iCode as comment */
13245 l = Safe_strdup(printILine(ic));
13246 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13249 /* if the result is marked as
13250 * spilt and rematerializable or code for
13251 * this has already been generated then
13253 if (resultRemat(ic) || ic->generated )
13256 /* depending on the operation */
13275 /* IPOP happens only when trying to restore a
13276 * spilt live range, if there is an ifx statement
13277 * following this pop then the if statement might
13278 * be using some of the registers being popped which
13279 * would destroy the contents of the register so
13280 * we need to check for this condition and handle it */
13282 && ic->next->op == IFX
13283 && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13284 genIfx (ic->next,ic);
13302 genEndFunction (ic);
13318 pic16_genPlus (ic) ;
13322 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13323 pic16_genMinus (ic);
13339 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13343 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13349 /* note these two are xlated by algebraic equivalence
13350 * during parsing SDCC.y */
13351 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13352 "got '>=' or '<=' shouldn't have come here");
13356 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13368 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13372 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13376 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13400 genRightShift (ic);
13403 case GET_VALUE_AT_ADDRESS:
13408 if (POINTER_SET(ic))
13435 addSet(&_G.sendSet,ic);
13438 case DUMMY_READ_VOLATILE:
13448 /* now we are ready to call the
13449 peep hole optimizer */
13450 if (!options.nopeep)
13451 peepHole (&lineHead);
13453 /* now do the actual printing */
13454 printLine (lineHead, codeOutFile);
13457 DFPRINTF((stderr,"printing pBlock\n\n"));
13458 pic16_printpBlock(stdout,pb);